Created
November 28, 2015 03:32
-
-
Save imran31415/fe273628cd4409977bd9 to your computer and use it in GitHub Desktop.
A python script to build web page tutorial templates based on JSON data
This file contains hidden or 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
import pprint | |
MANUAL_TEMPLATE = { | |
"title": "", | |
"header": "", | |
"warning": "Please make sure you have the following setup before starting", | |
"requirements":[], | |
"setup": | |
{ | |
"javascript_links": | |
""" | |
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha512-K1qjQ+NcF2TYO/eI3M6v8EiNYZfA95pQumfvcVrTHtwQVDG+aHRqLi/ETn2uB+1JqwYqVG3LIvdm9lj6imS/pQ==" crossorigin="anonymous"></script> | |
<script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js" async></script> | |
""", | |
"bootstrap_cdn": | |
''' | |
<!-- Latest compiled and minified CSS --> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha512-dTfge/zgoMYpP7QbHy4gWMEGsbsdZeCXz7irItjcC3sPUFtf0kuFbDz/ixG7ArTxmDjLXDmezHubeNikyKGVyQ==" crossorigin="anonymous"> | |
<!-- Optional theme --> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-aUGj/X2zp5rLCbBxumKTCw2Z50WgIr1vs/PFN4praOTvYXWlVyh2UtNUU0KAUhAX" crossorigin="anonymous"> | |
''' | |
}, | |
"end_result_image": {}, | |
"steps":[], | |
} | |
class TutorialConstructor(object): | |
def __init__(self, content): | |
self.content = content | |
def template_skeleton(self): | |
self.content['title'] = None | |
self.content['header'] = None | |
self.content['warning'] = None | |
self.content['requirements'] = [] | |
self.content["steps"] = [] | |
self.content['end_result_image'] = {} | |
def add_string_attribute(self, attribute, content): | |
if not attribute in ['title', 'header', 'warning']: | |
raise ValueError('Can only accept unicode or string types into title, header, warning elements of page') | |
self.string_validator([content]) | |
self.content[attribute] = content | |
def add_end_result(self, description, link): | |
self.string_validator([description]) | |
self.content['end_result_image']['end_result_image_description'] = description | |
self.content['end_result_image']['end_result_image_link'] = link | |
def add_step(self, title, description_before="", description_after="", step_number= False): | |
self.string_validator([title, description_before, description_after]) | |
if not step_number: | |
self.content['steps'].append(\ | |
{ | |
"title": title, | |
"description_before": description_before, | |
'sub_steps': [], | |
"description_after": description_after, | |
"code_assets":[], | |
"images": [], | |
'tables': [], | |
}) | |
if step_number: | |
step_number = step_number -1 | |
self.step_number_validator(step_number) | |
self.content['steps'].insert(step_number, | |
{ | |
"title": title, | |
"description_before": description_before, | |
'sub_steps': [], | |
"description_after": description_after, | |
"code_assets":[], | |
"images": [], | |
'tables': [], | |
}) | |
def add_step_sub_step(self, step_number, description, index= False): | |
step_number = step_number -1 | |
self.step_number_validator(step_number) | |
self.string_validator([description]) | |
if not index: | |
self.content['steps'][step_number]['sub_steps'].append(description) | |
else: | |
if index > len(self.content['steps'][step_number]['sub_steps']): | |
raise ValueError('substep index does not exist') | |
else: | |
self.content['steps'][step_number]['sub_steps'].insert(index-1,description) | |
def print_steps(self): | |
for x in self.content['steps']: | |
print '\n' | |
for k,v in x.items(): | |
print '\t', k, v | |
def printall(self): | |
pp = pprint.PrettyPrinter(depth=8) | |
pp.pprint(self.content) | |
def add_code_example(self, step_number, code_description, code_type, code_lines, index= False): | |
step_number = step_number-1 | |
self.string_validator([code_description, code_type, code_lines]) | |
if index and index> len(self.content['steps'][step_number]['code_assets']): | |
raise ValueError('code index does not exist') | |
if not index: | |
self.content['steps'][step_number]['code_assets'].append( | |
{ | |
'code_description': code_description, | |
'code_type':code_type, | |
'code_lines': code_lines | |
}) | |
else: | |
self.content['steps'][step_number]['code_assets'].insert(index-1, | |
{ | |
'code_description': code_description, | |
'code_type':code_type, | |
'code_lines': code_lines | |
}) | |
def add_image(self, step_number, image_description, image_link, index=False): | |
self.step_number_validator(step_number) | |
step_number= step_number-1 | |
self.string_validator([image_description, image_link]) | |
if index and index> len(self.content['steps'][step_number]['images']): | |
raise ValueError('image index does not exist') | |
if not index: | |
self.content['steps'][step_number]['images'].append( | |
{'image_description':image_description, 'image_link': image_link}) | |
elif index: | |
index = index-1 | |
self.content['steps'][step_number]['images'].insert(index, | |
{'image_description':image_description, 'image_link': image_link}) | |
def add_table(self, step_number, table_title, table_headers, table_rows, index = False): | |
self.list_validator([table_headers, table_rows]) | |
self.step_number_validator(step_number) | |
step_number = step_number -1 | |
self.string_validator(table_title) | |
if index and index > len(self.content['steps'][step_number]['tables']): | |
raise ValueError('table index does not exist') | |
if not index: | |
self.content['steps'][step_number]['tables'].append( | |
{ | |
'table_title': table_title, | |
'table_headers': table_headers, | |
'table_rows': table_rows | |
}) | |
elif index: | |
index = index -1 | |
self.content['steps'][step_number]['tables'].insert(index, | |
{ | |
'table_title': table_title, | |
'table_headers': table_headers, | |
'table_rows': table_rows | |
}) | |
def add_requirement(self, requirement, link = "#", index= False): | |
self.string_validator([requirement, link]) | |
if index: | |
if index > len(self.content['requirements']): | |
raise ValueError('The requirement index you want to insert at does not exist') | |
else: | |
index = index-1 | |
self.content['requirements'].insert(index, {requirement:link}) | |
else: | |
self.content['requirements'].append({requirement:link}) | |
def step_number_validator(self, step_number): | |
if step_number > len(self.content['steps']): | |
raise ValueError('The step you are trying to edit does not exist at the index specified') | |
def string_validator(self, strings): | |
if not all(map (lambda x: isinstance(x,(str,unicode)), strings)): | |
raise ValueError('Can only accept unicode or string types into the element') | |
def list_validator(self, lists): | |
if not all(map (lambda x: isinstance(x, (list)), lists)): | |
raise ValueError('can only enter list into the element') | |
def construct_overview_html(self): | |
payload = ''' | |
<div class="container" id="headdingsection"> | |
<div class ="row"> | |
<div class="col-md-7 col-lg-6 col-sm-7"> | |
<h3> Overview of steps: </h3> | |
<ul class="list-group" > | |
''' | |
steps = [x['title'] for x in self.content['steps']] | |
for i, step in enumerate(steps): | |
payload+=''' | |
<li class="list-group-item"> | |
<span class="label label-default label-pill pull-right">{}</span> | |
{} | |
</li> | |
'''.format(i+1,step) | |
payload += ''' | |
</ul> | |
</div> | |
''' | |
return payload | |
def construct_step_html(self, step, number): | |
payload = ''' | |
<div class ="container"><div class="row"> | |
<br /><br /> | |
<div class="panel panel-default"> | |
<div class="panel-heading">{}. {}</div> | |
<div class="panel-body"> | |
<div class ="col-md-8 col-lg-8 col-sm-10"> | |
<p class = "description_before"> {}</p> | |
<ol class = "sub_steps"> | |
'''.format(number, step['title'], step['description_before']) | |
for x in step['sub_steps']: | |
payload+=''' | |
<li> {}</li> | |
'''.format(x) | |
payload += ''' | |
</ol> | |
<p class= "description_after"> {} <br><br></p> | |
</div>'''.format(step['description_after']) | |
for asset in step['code_assets']: | |
payload += ''' | |
<div class="col-md-8 col-lg-6 col-sm-12"> | |
<hr> | |
<h5 class= "code_description"> {}</h5> | |
<pre style = "font-size:10px;" class="prettyprint linenums lang-{} code_type code_lines"> | |
<script style = "display:block;" type="text/plain"> | |
{} | |
</script> | |
</pre> | |
</div>'''.format(asset['code_description'], asset['code_type'],asset['code_lines']) | |
for image in step['images']: | |
payload += ''' | |
<div class ="col-md-8 col-lg-6 col-sm-10"> | |
<hr> | |
<h5> {}</h5> | |
<img class = "img-responsive img-thumbnail" src="{}" alt="" /> | |
</div> | |
'''.format(image['image_description'], image['image_link']) | |
for table in step['tables']: | |
payload += ''' | |
<div class = "col-md-8 col-lg-6 col-sm-10"> | |
<hr> | |
<h4>{}</h4> | |
<table class="table table-bordered table-condensed"> | |
<thead> | |
<tr> | |
'''.format(table['table_title']) | |
for header in table['table_headers']: | |
payload += ''' | |
<th>{}</th> | |
'''.format(header) | |
payload += ''' | |
</tr> | |
</thead> | |
<tbody> | |
''' | |
for row in table['table_rows']: | |
payload += ''' | |
<tr>''' | |
for i in row: | |
payload += "<td>{}</td>".format(i) | |
payload += ''' | |
</tr>''' | |
payload += ''' | |
</tbody> | |
</table> | |
</div> | |
''' | |
payload += ''' | |
</div> | |
</div> | |
</div> | |
</div><hr>''' | |
return payload | |
def construct_requirements_html(self): | |
payload = ''' | |
<div class = "col-md-4 col-sm-4 col-lg-4"> | |
<div class="requirements"> | |
<div class="alert alert-warning"> | |
<p>Before starting this tutorial, please ensure you have the following: </p> | |
</div> | |
<a href="#" class="list-group-item active"> | |
REQUIREMENTS | |
</a> | |
''' | |
for dic in self.content['requirements']: | |
k, v = dic.keys()[0], dic.values()[0] | |
payload += ''' | |
<a href="{}" class="list-group-item">{}</a> | |
'''.format(v,k) | |
payload += ''' | |
</div> | |
</div> | |
</div> | |
</div> | |
<hr> | |
''' | |
return payload | |
def aggregate_steps_html(self): | |
payload = "" | |
for i, step in enumerate(self.content['steps']): | |
payload+= self.construct_step_html(step, i+1) | |
return payload | |
def construct_html(self): | |
doc_start = ''' | |
<!DOCTYPE html> | |
<html> | |
''' | |
doc_head_start = ''' | |
<head> | |
''' | |
doc_head_end = ''' | |
</head> | |
<body> | |
''' | |
doc_head_tag = \ | |
doc_head_start + \ | |
self.content['setup']['javascript_links'] + \ | |
self.content['setup']['bootstrap_cdn'] + \ | |
doc_head_end | |
doc_end = ''' | |
</body> | |
</html> | |
''' | |
doc_title = ''' | |
<div class="container"> | |
<div class ="row"> | |
<div class = "col-md-6 col-lg-6 col-sm-9 col-xs-9"> | |
<h1 class= "page-header">{}</h1> | |
</div> | |
</div> | |
</div> | |
'''.format(self.content['title']) | |
doc_header = ''' | |
<div class="container"> | |
<div class ="row"> | |
<div class = "col-md-8 col-lg-8 col-sm-9 col-xs-9"> | |
<p> | |
{} | |
<p> | |
<hr> | |
</div> | |
</div> | |
</div> | |
'''.format(self.content['header']) | |
if self.content['end_result_image']: | |
doc_end_result_preview = ''' | |
<div class="container"> | |
<div class ="row"> | |
<div class = "col-md-7 col-lg-6 col-sm-10 col-xs-10"> | |
<h3> Preview of end result: </h3> | |
<h4> {}</h4> | |
<img class = "img-responsive img-thumbnail" src="{}" alt="" /> | |
<br /><br /> | |
</div> | |
</div> | |
</div> | |
'''.format(\ | |
self.content['end_result_image']['end_result_image_description'], \ | |
self.content['end_result_image']['end_result_image_link']\ | |
) | |
else: | |
doc_end_result_preview ="" | |
TEMPLATE = \ | |
doc_start + \ | |
doc_head_tag + \ | |
doc_title+ \ | |
doc_header+ \ | |
self.construct_overview_html()+\ | |
self.construct_requirements_html()+\ | |
self.aggregate_steps_html()+\ | |
doc_end_result_preview+\ | |
doc_end | |
print TEMPLATE | |
t = TutorialConstructor(MANUAL_TEMPLATE) | |
#Tutorial.print_items() | |
t.template_skeleton() | |
#Tutorial.print_items() | |
t.add_string_attribute('title', 'How to make an html tutorial template builder using json, python and bootstrap') | |
t.add_string_attribute('header', '- Using Python, and bootstrap generate html tutorials easily and store them as JSON data for easy modifications. This page was built using the tutorial builder!' ) | |
t.add_requirement('Python 2.7', 'https://www.python.org/downloads/') | |
t.add_requirement('Text Editor') | |
t.add_requirement('HTML/CSS/JS viewer ex. codepen.io', 'http://www.codepen.io') | |
t.add_step(title= 'Deveop the json data structure which will hold the tutorial information', | |
description_before= 'We need to store information about the tutorial and \ | |
organize it into a json data structure. The basic things we need is a title, \ | |
header, requirements, steps, and information related to each step including images,\ | |
code examples, tables and substeps', | |
description_after= 'If you look at the basic structure below you will notice it has the skeleton for the above elements') | |
t.add_step_sub_step(1, 'Title') | |
t.add_step_sub_step(1, 'Header') | |
t.add_step_sub_step(1, 'Requirements') | |
t.add_step_sub_step(1, 'Setup (bootstrap/js links') | |
t.add_step_sub_step(1, 'Each step and its respective assets [code, images, tables]') | |
t.add_step_sub_step(1, 'Deliverable images') | |
t.add_image(1, 'With links added: ', 'http://i.imgur.com/tvs3CkP.png') | |
t.add_code_example(1, 'The JSON structure to store tutorial data: ', 'py', """\ | |
MANUAL_TEMPLATE = { | |
"title": "", | |
"header": "", | |
"warning": "Please make sure you have the following setup before starting", | |
"requirements":[], | |
"setup": | |
{ | |
"javascript_links": "" | |
"bootstrap_cdn": "" | |
}, | |
"end_result_image": {}, | |
"steps":[], | |
} | |
""") | |
t.add_step(title= 'Define a class with methods to add/modify data into the json template', | |
description_before= 'We can store the json data as a class variable and modify the different aspects by defining class functions', | |
description_after= 'The image below shows the scaffolding for the class. The code below shows an example of how the class method of adding a step to the tutorial is defined') | |
t.add_code_example(2, 'Implementing a function to add a step to the tutorial', 'py',\ | |
""" | |
def add_step(self, title, description_before="", description_after="", step_number= False): | |
self.string_validator([title, description_before, description_after]) | |
if not step_number: | |
self.content['steps'].append(\ | |
{ | |
"title": title, | |
"description_before": description_before, | |
'sub_steps': [], | |
"description_after": description_after, | |
"code_assets":[], | |
"images": [], | |
'tables': [], | |
}) | |
if step_number: | |
step_number = step_number -1 | |
self.step_number_validator(step_number) | |
self.content['steps'].insert(step_number, | |
{ | |
"title": title, | |
"description_before": description_before, | |
'sub_steps': [], | |
"description_after": description_after, | |
"code_assets":[], | |
"images": [], | |
'tables': [], | |
}) | |
""") | |
t.add_image(2, 'TutorialConstructor class outline ', 'http://i.imgur.com/OhxrPeg.png') | |
t.add_step(title= 'Define class methods to construct the html from the data provided into a tutorial template', | |
description_before= 'This is a bit tedious to write a bunch of custom code to integrate in the json data into a bootstrap html template', | |
description_after= 'Iterate over the different template variables to supply the correct html tags') | |
t.add_code_example(3, 'An example function to template in the overview section which shows all the step titles in the top', 'py',\ | |
""" | |
def construct_overview_html(self): | |
payload = ''' | |
<div class="container" id="headdingsection"> | |
<div class ="row"> | |
<div class="col-md-7 col-lg-6 col-sm-7"> | |
<h3> Overview of steps: </h3> | |
<ul class="list-group" > | |
''' | |
steps = [x['title'] for x in self.content['steps']] | |
for i, step in enumerate(steps): | |
payload+=''' | |
<li class="list-group-item"><span class="badge">{}</span>{}</p></li> | |
'''.format(i+1,step) | |
payload += ''' | |
</ul> | |
</div> | |
''' | |
return payload | |
""") | |
t.add_table(3, 'Can template in-line tables as well for example:', ['username', 'email', 'department', 'start_date'], [['develop.imran', '[email protected].', 'IT', '2014-01-01'],['albert', '[email protected]', 'accounting', '2015-01-01']], index = False) | |
t.add_step(title= 'Start using the class & functions to create a tutorial template', | |
description_before= 'Using the functions we defined earlier, we can add data to the json and build the html for the tutorial', | |
description_after= 'If you do not like using the functions, you can always edit the JSON data directly. See code below for example of creating a tutorial template') | |
t.add_code_example(4, 'An example function to template in the overview section which shows all the step titles in the top', 'py',\ | |
""" | |
t.add_string_attribute('title', 'How to make an html tutorial template builder using json, python and bootstrap') | |
t.add_string_attribute('header', '- Using Python, and bootstrap generate html tutorials easily and store them as JSON data for easy modifications. This page was built using the tutorial builder!' ) | |
t.add_requirement('Python 2.7', 'https://www.python.org/downloads/') | |
t.add_requirement('Text Editor') | |
t.add_requirement('HTML/CSS/JS viewer ex. codepen.io', 'http://www.codepen.io') | |
t.add_step(title= 'Deveop the json data structure which will hold the tutorial information', | |
description_before= 'We need to store information about the tutorial and \ | |
organize it into a json data structure. The basic things we need is a title, \ | |
header, requirements, steps, and information related to each step including images,\ | |
code examples, tables and substeps', | |
description_after= 'If you look at the basic structure below you will notice it has the skeleton for the above elements') | |
t.add_step_sub_step(1, 'Title') | |
t.add_step_sub_step(1, 'Header') | |
t.add_step_sub_step(1, 'Requirements') | |
t.add_step_sub_step(1, 'Setup (bootstrap/js links') | |
t.add_step_sub_step(1, 'Each step and its respective assets [code, images, tables]') | |
t.add_step_sub_step(1, 'Deliverable images') | |
t.add_image(1, 'With links added: ', 'http://i.imgur.com/tvs3CkP.png') | |
t.add_code_example(1, 'The JSON structure to store tutorial data: ', 'py', '''\ | |
MANUAL_TEMPLATE = { | |
"title": "", | |
"header": "", | |
"warning": "Please make sure you have the following setup before starting", | |
"requirements":[], | |
"setup": | |
{ | |
"javascript_links": "" | |
"bootstrap_cdn": "" | |
}, | |
"end_result_image": {}, | |
"steps":[], | |
} | |
''' | |
""") | |
t.add_image(4, 'if you notice, these commands are building the tutorial you are reading now.', 'http://i.imgur.com/t5PIWP5.png') | |
t.construct_html() | |
#Tutorial.printall() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment