Last active
August 29, 2015 13:57
-
-
Save tkhduracell/9539269 to your computer and use it in GitHub Desktop.
A small Python class to build Bootstrap html documents with a pretty function syntax.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from datetime import datetime | |
import os | |
import types | |
import functools | |
import my_utils | |
class PyStrapper: | |
name = "" | |
output = "" | |
output_handler = False | |
output_element_stack = [] | |
def __init__(self, output_file="default.html", name="My Report"): | |
self.name = name | |
self.output = output_file | |
try: | |
self.output_handler = open(output_file, "w") | |
except Exception as e: | |
raise Exception("Can not read file: "+output_file + "\n" + str(e)) | |
def __repr__(self): | |
return "%s: name=%s, output=%s" % (self.__class__.__name__,self.name, self.output) | |
def write(self, str): | |
self.output_handler.write(str) | |
def init(self): | |
supported = ["section", "nav", "article", "aside", "header", "footer", "address", "main", "p", "hr", "pre", "blockquote", "ol", "ul", "li", "dl", "dt","dd", "dd", | |
"figure", "figcaption", "div", "a", "em", "strong", "small", "s", "cite", "q", "dfn", "abbr" "title", "data", "time", "datetime", "code", "var", "samp", "kbd", | |
"sub", "sup", "i", "b", "u", "mark", "ruby", "rt", "rp", "bdi", "bdo", "span" "classlangdir", "br", "wbr", "ins", "del", "img ", "iframe", "embed", "object", | |
"param", "object", "video", "audio", "source", "video", "audio", "track", "video", "audio", "canvas", "map", "area", "area", "map", "svg", "math", "table", | |
"caption", "colgroup", "col", "tbody", "thead", "tfoot", "tr", "td", "th", "form", "fieldset", "legend", "fieldset", "label", "input", "button", "select", | |
"datalist", "optgroup", "option", "select", "datalist", "textarea", "keygen", "output", "progress", "meter", "details", "summary", "details", "menuitem", "menu"] | |
supported.extend(["h%d" % (s,) for s in range(1,7)]) | |
def bind_to_class(func, name, obj, tag): | |
func.__name__ = name | |
setattr(obj.__class__, func.__name__, functools.partial(func, obj, tag)) | |
for tag in sorted(supported): | |
def dynamic_begin(self, the_tag): | |
self.wrapper_begin(the_tag) | |
return self | |
bind_to_class(dynamic_begin, tag+"_begin", self, tag) | |
def dynamic_end(self, the_tag): | |
self.wrapper_end(the_tag) | |
return self | |
bind_to_class(dynamic_end, tag+"_end", self, tag) | |
def dynamic_plain(self, the_tag, *args, **kwargs): | |
if len(args) > 1: | |
raise Exception("Multiple content not supported, [0,1]") | |
if len(args) == 1: | |
kwargs['_content'] = args[0] | |
self.plain_element(the_tag, kwargs) | |
return self | |
bind_to_class(dynamic_plain, tag, self, tag) | |
return self | |
def begin(self): | |
header = """ | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="Content-type" content="text/html;charset=UTF-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title><!--MY_TITLE--></title> | |
<!-- Latest compiled and minified CSS --> | |
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"> | |
<!-- Optional theme --> | |
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css"> | |
<!-- Latest compiled and minified JavaScript --> | |
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> | |
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.js"></script> | |
<style> | |
html { | |
position: relative; | |
min-height: 100%; | |
} | |
body { | |
margin-top: 60px; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation"> | |
<div class="container"> | |
<div class="navbar-header"> | |
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> | |
<span class="sr-only">Toggle navigation</span> | |
<span class="icon-bar"></span> | |
<span class="icon-bar"></span> | |
<span class="icon-bar"></span> | |
</button> | |
<a class="navbar-brand" href="#"><!--MY_TITLE--></a> | |
</div> | |
<div class="collapse navbar-collapse"> | |
<ul class="nav navbar-nav"> | |
<!--<li class='active' ><a href="index.php">Start</a></li>--> | |
</ul> | |
</div><!--/.nav-collapse --> | |
</div> | |
</div> | |
<div class="container"> | |
<div class="starter-template"> | |
<!-- content goes here --> | |
""" | |
self.write(header.replace("<!--MY_TITLE-->", self.name, 2)) | |
self.init() | |
return self | |
def end(self): | |
footer = """ | |
<hr> | |
<footer class="text-muted small"> | |
<span class="pull-left">%s <br>© Filip Lindqvist 2014</span> | |
<span class="pull-right">Report generated %s</span> | |
</footer> | |
</div><!-- /.container --> | |
</body> | |
</html> | |
""" | |
self.write(footer % (self.__class__.__name__,datetime.today().strftime("%Y-%m-%d %H:%M:%S"),)) | |
self.output_handler.close() | |
return self | |
def wrapper_begin(self, tag): | |
self.output_element_stack.append(tag) | |
self.write("<%s>" % (tag,)) | |
return self | |
def wrapper_end(self, tag): | |
if self.output_element_stack[-1] is tag: | |
self.output_element_stack.pop() | |
self.write("</%s>\n" % (tag,)) | |
return self | |
else: | |
raise Exception("Not in a %s, stack: %s" % (tag, str(self.output_element_stack))) | |
def plain_element(self, tag, attr): | |
attribute_str = " ".join( | |
[("%s=\"%s\"" % (key,value)) | |
for key, value in attr.items() | |
if key not in ("_content") | |
] | |
) | |
if "_content" in attr: | |
content = attr['_content'] | |
self.write("<%s %s>%s</%s>\n" % (tag, attribute_str, content, tag)) | |
else: | |
self.write("<%s %s/>\n" % (tag, attribute_str)) | |
return self | |
def main(): | |
(PyStrapper("test.html", "My Test Report").begin() | |
.br() | |
.h3("h3. Bootstrap heading") | |
.p("This is a sample unordered list") | |
.ul_begin() | |
.li("test1") | |
.li("test2") | |
.ul_end() | |
.p("This is a sample ordered list", style="color:blue") | |
.ol_begin() | |
.li("test1") | |
.li("test2") | |
.ol_end() | |
.end()) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment