Skip to content

Instantly share code, notes, and snippets.

@imran31415
Created November 28, 2015 03:32
Show Gist options
  • Save imran31415/fe273628cd4409977bd9 to your computer and use it in GitHub Desktop.
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
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