%load_ext autoreload
%autoreload 2
import os
import ezdashboard as ed
from ezdashboard.elements import Div, ListDiv, Title, Row, Tab, ListJs, Misc, Header, Dashboard
The purpose of this notebook is to produce a nicely formatted dashboard from several HTML contents using module ezdashboard
.
is_markdown=True
, then the content will be converted to HTMLThe following demo is meant to show how to use this module.
width
: width of div in bootstrap format i.e. as integer from 1 to 12id_name
: name of id (optional)class_name
: name of class (optional)with_borders
: bool to indicate if div has bordersmain_type
: bootstrap container style, can be container
or container-fluid
main_nav_width
: css with property of primary (left side) tabsmain_content_width
: css with property of contentmain_nav_min_height
: css with property of a tab min-heightno_margins
: bool to indicate if tiles are slightly separated or notleft_logo
: path to image for left logo - must be square to avoid distortionleft_title
: string for header title, next to the left side logoright_logo
: path to image for right logo - must be square to avoid distortiontoggle
: bool to indicate if the toggle button is showed (demo)A Dashboard object can be created from these objects.
Then it can generate the resulting web page as a string and/or file.
with open(os.path.join('data', 'markdown_sample_1.md')) as f:
content = f.read()
def md(n, w, verbose=True):
"""
make Div helper
w is width bootstrap style i.e. as 1/12 of width available
"""
data = {
'id_name': 'myname-'+str(n),
'class_name': 'my-style-'+str(n),
'content': 'I am Block '+str(n) if n < 12 else content,
'width': w,
'with_borders': bool(n % 2),
'is_markdown': False if n < 12 else True
}
if verbose:
print('div created:', data)
return Div(**data)
d1, d2 = md(0, 6), md(1, 6)
d3, d4, d5 = md(2, 4), md(3, 4), md(4, 4)
d6, d7 = md(5, 4), md(6, 2)
d8, d9 = md(7, 8), md(8, 4)
d10, d11, d12 = md(9, 12), md(10, 12), md(11, 6)
d13 = md(12, 12)
div created: {'id_name': 'myname-0', 'class_name': 'my-style-0', 'content': 'I am Block 0', 'width': 6, 'with_borders': False, 'is_markdown': False} div created: {'id_name': 'myname-1', 'class_name': 'my-style-1', 'content': 'I am Block 1', 'width': 6, 'with_borders': True, 'is_markdown': False} div created: {'id_name': 'myname-2', 'class_name': 'my-style-2', 'content': 'I am Block 2', 'width': 4, 'with_borders': False, 'is_markdown': False} div created: {'id_name': 'myname-3', 'class_name': 'my-style-3', 'content': 'I am Block 3', 'width': 4, 'with_borders': True, 'is_markdown': False} div created: {'id_name': 'myname-4', 'class_name': 'my-style-4', 'content': 'I am Block 4', 'width': 4, 'with_borders': False, 'is_markdown': False} div created: {'id_name': 'myname-5', 'class_name': 'my-style-5', 'content': 'I am Block 5', 'width': 4, 'with_borders': True, 'is_markdown': False} div created: {'id_name': 'myname-6', 'class_name': 'my-style-6', 'content': 'I am Block 6', 'width': 2, 'with_borders': False, 'is_markdown': False} div created: {'id_name': 'myname-7', 'class_name': 'my-style-7', 'content': 'I am Block 7', 'width': 8, 'with_borders': True, 'is_markdown': False} div created: {'id_name': 'myname-8', 'class_name': 'my-style-8', 'content': 'I am Block 8', 'width': 4, 'with_borders': False, 'is_markdown': False} div created: {'id_name': 'myname-9', 'class_name': 'my-style-9', 'content': 'I am Block 9', 'width': 12, 'with_borders': True, 'is_markdown': False} div created: {'id_name': 'myname-10', 'class_name': 'my-style-10', 'content': 'I am Block 10', 'width': 12, 'with_borders': False, 'is_markdown': False} div created: {'id_name': 'myname-11', 'class_name': 'my-style-11', 'content': 'I am Block 11', 'width': 6, 'with_borders': True, 'is_markdown': False} div created: {'id_name': 'myname-12', 'class_name': 'my-style-12', 'content': '\n# Written in Markdown\n\n## Latex\n\nCourtesy of [MathJax](https://www.mathjax.org/). \nYou can include mathematical expressions both inline: $ e^{i\\pi} + 1 = 0 $ and displayed as block:\n\n$$ e^x=\\sum_{i=0}^\\infty \\frac{x^i}{i!} $$\n\nTo practise your Latex I recommend the [codecogs latex equation online editor](https://www.codecogs.com/latex/eqneditor.php).\n\n\n\n## Colors\n\nSometimes you need to use colors to draw attention.\n\n<span style="color:blue">Hey *This is Blue italic.* text</span>\n\n<span style="color:red">Hey **This is Red Bold.** text</span>\n\n## Lists\n\n1. First ordered list item\n2. Another item\n * Unordered sub-list. \n1. Actual numbers don\'t matter, just that it\'s a number\n 1. Ordered sub-list\n 1. Ordered sub-list other item\n4. And another item.\n\n You can have properly indented paragraphs within list items. Notice the blank line above, and the leading spaces (at least one, but we\'ll use three here to also align the raw Markdown).\n\n To have a line break without a paragraph, you will need to use two trailing spaces. \n Note that this line is separate, but within the same paragraph. \n (This is contrary to the typical GFM line break behaviour, where trailing spaces are not required.)\n\n* Unordered list can use asterisks\n- Or minuses\n+ Or pluses\n\n## Tables\n\nTables aren\'t part of the core Markdown spec, but they are part of GFM and Markdown Here supports them. They are an easy way of adding tables to your email -- a task that would otherwise require copy-pasting from another application.\n\nColons can be used to align columns.\n\n| Tables | Are | Cool |\n| ------------- |:-------------:| -----:|\n| col 3 is | right-aligned | $1600 |\n| col 2 is | centered | $12 |\n| zebra stripes | are neat | $1 |\n\nThere must be at least 3 dashes separating each header cell.\nThe outer pipes (|) are optional, and you don\'t need to make the \nraw Markdown line up prettily. You can also use inline Markdown.\n\nMarkdown | Less | Pretty\n--- | --- | ---\n*Still* | `renders` | **nicely**\n1 | 2 | 3\n', 'width': 12, 'with_borders': False, 'is_markdown': True}
css = """
/* IMPORTANT: tile is a KEYWORD */
/* It is the class of all display divs in the dashboard tabs */
.tile {
padding: 15px;
margin: 17.5px;
font-size: 1.6rem;
}
.nav-tab {
font-family: 'Source Sans Pro', Arial, sans-serif;
color: #333333;
}
/* IMPORTANT: tile is a KEYWORD */
/* It is the class of all display divs in the dashboard tabs */
.header img.left-logo {
width: 46px;
height: 46px;
}
.header img.right-logo {
width: 46px;
height: 46px;
}
.my-style-0 {
height: 200px;
background-color: red;
}
.my-style-1 {
height: 80px;
background-color: blue;
}
.my-style-2 {
height: 100px;
background-color: green;
}
.my-style-3 {
height: 60px;
background-color: yellow;
}
.my-style-4 {
height: 100px;
background-color: orange;
}
.my-style-5 {
height: 100px;
background-color: lightpink;
}
.my-style-6 {
padding: 15px;
height: 150px;
background-color: lightblue;
}
.my-style-7 {
height: 100px;
background-color: lightgray;
}
.my-style-8 {
height: 100px;
background-color: purple;
}
.my-style-9 {
height: 100px;
background-color: yellow;
}
.my-style-10 {
height: 120px;
background-color: red;
}
.my-style-11 {
height: 240px;
background-color: green;
}
.my-style-12 {
height: 1700px;
}
.special_row {
border: 2px red;
}
.wrapper {
width: 1000px;
margin-top: 15px;
}
"""
ListDiv
(s) and Row
(s)Title
elementsTab
(s)Tab
(s) in a Tab
Mics
Header
if you needtitle
goes in the header if it is defined else at above the tabs areatoogle
is only here for testing - set to False in productionmarkdown_div
is a list of Div whose content is in Markdown - if anylatex
must be set to True if any any content requires it - typically markdown with formulaeFor a really thorough view of what these variables imply, check out the dashboard jinja template.
li_d1 = ListDiv(**{'elmts': [d1, d2]})
li_d2 = ListDiv(**{'elmts': [d3, d4, d5]})
li_d3 = ListDiv(**{'elmts': [d6, d7]})
li_d4 = ListDiv(**{'elmts': [d8, d9]})
li_d5 = ListDiv(**{'elmts': [d10, d11], 'width': 6, 'class_name': 'listdiv_name', 'level': 2})
li_d6 = ListDiv(**{'elmts': [li_d5, d12]})
li_d7 = ListDiv(**{'elmts': [d13]})
row1 = Row(**{'elmts': li_d1})
row2 = Row(**{'elmts': li_d2})
row3 = Row(**{'elmts': li_d3})
row4 = Row(**{'elmts': li_d4})
row5 = Row(**{'elmts': li_d6, 'class_name': 'special_row'})
row6 = Row(**{'elmts': li_d7})
title1 = Title(**{'size': 2, 'text': 'MyTitle1'})
title2 = Title(**{'size': 3, 'text': 'MyTitle2'})
title3 = Title(**{'size': 4, 'text': 'MyTitle3'})
title4 = Title(**{'size': 3, 'text': 'MyTitle4'})
tab1 = Tab(**{'name': 'Tab1', 'elmts': [title1, row1, row2]})
tab2 = Tab(**{'name': 'Tab2', 'elmts': [title2, row3, row4], 'active': True})
tab31 = Tab(**{'name': 'MyTab31', 'elmts': [row1, row2], 'level': 2})
tab32 = Tab(**{'name': 'MyTab32', 'elmts': [row3, row4], 'level': 2, 'active': True})
tab3 = Tab(**{'name': 'Rather long tab title that spans several lines', 'elmts': [tab31, tab32]})
tab41 = Tab(**{'name': 'MyTab41', 'elmts': [title3, row5], 'level': 2, 'active': True})
tab42 = Tab(**{'name': 'MyTab42', 'elmts': [title4, row6], 'level': 2})
tab4 = Tab(**{'name': 'Tab4', 'elmts': [tab41, tab42]})
js = ListJs(['http://example.js'])
titleD = Title(**{'size': 2, 'text': 'MyGlobalTitle'})
misc= Misc(**{'main_type': 'container-fluid',
'main_class_name': 'wrapper',
'main_nav_width': '17%',
'main_nav_min_height': '15%',
'main_content_width': '82%',
'no_margins': False,
})
header = Header(**{'left_logo': os.path.join('img', 'sg-logo.png'),
'left_title': 'HF-Hub',
'right_logo': os.path.join('img', 'jupyter-logo.png'),
'toggle': True
})
dashboard = Dashboard(**{'title': titleD,
'tabs': [tab1, tab2, tab3, tab4],
'css': css,
'js': js,
'misc': misc,
'header': header,
'markdown': True,
'widgets': False,
'widgets_state': [],
'latex': True
}, verbose=True)
Dashboard: isTitle= True Dashboard: isTabs= True Dashboard: isJs= True Dashboard: isMisc= True Dashboard: isExactlyOneActiveTab= True Dashboard: isHeader= True Dashboard: isMarkdown= True Dashboard: isWidgets= True Dashboard: isWidgetsState= True Dashboard: isLatex= True Dashboard: isDashboard= True
build()
has the following arguments:
save=True
, optionally save_name
(default='index.html'), optionally save_path
(default='saved')save=False
will return the HTML content as a stringIt will save the dashboard as a file under save_path
after creating this folder it if necessary.
data = dashboard.to_dict()
content = ed.build(data, save=False)
ed.build(data, save=True, save_path='sample')
file sample/index.html created on disk file sample/server.sh created on disk: python -m http.server 8081 Run it to launch web server and test dashboard
minified_content = ed.minify(content)
print(minified_content[:1000])
print('\n...{} more characters...\n'.format(len(minified_content)-2000))
print(minified_content[-1000:])
<!DOCTYPE html> <html lang="en"> <head> <title>Dashboard</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Libs --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <!-- Fonts --> <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro" rel="stylesheet"> <!-- Libs --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/2.8.0/github-markdown.min.css"> <!-- Load RequireJS, used by the IPywidgets for dependency management --> <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js" integrity="sha256-Ae2Vz/4ePdIu6ZyI/5ZGsYnb+m0 ...53843 more characters... ht key is pressed'); if (activeTab in activeTabL2) { activeTabL2[activeTab] = modulo(activeTabL2[activeTab] + 1, nbTabL2[activeTab]); var tabName = 'tab' + activeTab + '-' + activeTabL2[activeTab] + 'Link'; } break; } if (tabName) { console.log('tabName clicked = '+tabName); document.getElementById(tabName).click(); } }; $('.theme-toggle').on('click', function() { $('body').toggleClass('dark-theme'); }); </script> <script type="text/x-mathjax-config"> MathJax.Hub.Config( {TeX: { Macros: { sp: "^", sb: "_" } }, tex2jax: { inlineMath: [ ['$','$'], ['\\(','\\)'] ], displayMath: [ ["$$","$$"], ["\\[","\\]"] ] } }); </script> <script type='text/javascript'> setTimeout(function () { var headID = document.getElementsByTagName('head')[0]; var newScript = document.createElement('script'); newScript.type = 'text/javascript'; newScript.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML'; headID.appendChild(newScript); }, 1000); </script> </body> </html>
# with open(os.path.join('sample', 'index.html'), 'w') as f:
# f.write(minified_content)
Dashboard
, Tab
, Title
, Row
, ListDiv
, Div
, Misc
and Header
essentially represent dictionaries with constraints..to_dic()
and pretty-print .pprint()
..to_dic()
the method.d1.to_dict()
{'type': 'Div', 'id_name': 'myname-0', 'class_name': 'my-style-0', 'content': 'I am Block 0', 'width': 6, 'is_markdown': False, 'with_borders': False, 'valid': True}
d1.pprint()
{ "class_name": "my-style-0", "content": "I am Block 0", "id_name": "myname-0", "is_markdown": false, "type": "Div", "valid": true, "width": 6, "with_borders": false }
li_d1.to_dict()
{'type': 'ListDiv', 'width': 12, 'elmts': [{'type': 'Div', 'id_name': 'myname-0', 'class_name': 'my-style-0', 'content': 'I am Block 0', 'width': 6, 'is_markdown': False, 'with_borders': False, 'valid': True}, {'type': 'Div', 'id_name': 'myname-1', 'class_name': 'my-style-1', 'content': 'I am Block 1', 'width': 6, 'is_markdown': False, 'with_borders': True, 'valid': True}], 'level': 1, 'valid': True}
li_d1.pprint()
{ "elmts": [ { "class_name": "my-style-0", "content": "I am Block 0", "id_name": "myname-0", "is_markdown": false, "type": "Div", "valid": true, "width": 6, "with_borders": false }, { "class_name": "my-style-1", "content": "I am Block 1", "id_name": "myname-1", "is_markdown": false, "type": "Div", "valid": true, "width": 6, "with_borders": true } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }
li_d1.elmts[0].pprint()
{ "class_name": "my-style-0", "content": "I am Block 0", "id_name": "myname-0", "is_markdown": false, "type": "Div", "valid": true, "width": 6, "with_borders": false }
.to_dict()
¶li_d1.to_dict()['elmts'][0]
{'type': 'Div', 'id_name': 'myname-0', 'class_name': 'my-style-0', 'content': 'I am Block 0', 'width': 6, 'is_markdown': False, 'with_borders': False, 'valid': True}
title1.pprint()
{ "size": 2, "text": "MyTitle1", "type": "Title", "valid": true }
row1.pprint()
{ "elmts": { "elmts": [ { "class_name": "my-style-0", "content": "I am Block 0", "id_name": "myname-0", "is_markdown": false, "type": "Div", "valid": true, "width": 6, "with_borders": false }, { "class_name": "my-style-1", "content": "I am Block 1", "id_name": "myname-1", "is_markdown": false, "type": "Div", "valid": true, "width": 6, "with_borders": true } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true }
tab3.pprint()
{ "active": false, "elmts": [ { "active": false, "elmts": [ { "elmts": { "elmts": [ { "class_name": "my-style-0", "content": "I am Block 0", "id_name": "myname-0", "is_markdown": false, "type": "Div", "valid": true, "width": 6, "with_borders": false }, { "class_name": "my-style-1", "content": "I am Block 1", "id_name": "myname-1", "is_markdown": false, "type": "Div", "valid": true, "width": 6, "with_borders": true } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true }, { "elmts": { "elmts": [ { "class_name": "my-style-2", "content": "I am Block 2", "id_name": "myname-2", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": false }, { "class_name": "my-style-3", "content": "I am Block 3", "id_name": "myname-3", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": true }, { "class_name": "my-style-4", "content": "I am Block 4", "id_name": "myname-4", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": false } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true } ], "level": 2, "name": "MyTab31", "type": "Tab", "valid": true }, { "active": true, "elmts": [ { "elmts": { "elmts": [ { "class_name": "my-style-5", "content": "I am Block 5", "id_name": "myname-5", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": true }, { "class_name": "my-style-6", "content": "I am Block 6", "id_name": "myname-6", "is_markdown": false, "type": "Div", "valid": true, "width": 2, "with_borders": false } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true }, { "elmts": { "elmts": [ { "class_name": "my-style-7", "content": "I am Block 7", "id_name": "myname-7", "is_markdown": false, "type": "Div", "valid": true, "width": 8, "with_borders": true }, { "class_name": "my-style-8", "content": "I am Block 8", "id_name": "myname-8", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": false } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true } ], "level": 2, "name": "MyTab32", "type": "Tab", "valid": true } ], "level": 1, "name": "Rather long tab title that spans several lines", "type": "Tab", "valid": true }
js.pprint()
[ "http://example.js" ]
misc.pprint()
{ "main_class_name": "wrapper", "main_content_width": "82%", "main_nav_min_height": "15%", "main_nav_width": "17%", "main_type": "container-fluid", "no_margins": false, "type": "Misc", "valid": true }
header.pprint()
{ "left_logo": "img/sg-logo.png", "left_logo_img_src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMcAAADHCAYAAACtBUfGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAZ7SURBVHhe7dpNqyRnGcfhqu55JYgbYTQGF+4E0UHEhQv9FApCXLgQFQ24UdxICAS/ldus/QQicSWZJDOiEDzdXd53VZ8hzMx/mfMceq7rpE53Vw+c...(2128 more characters)", "left_title": "HF-Hub", "right_logo": "img/jupyter-logo.png", "right_logo_img_src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQEAYAAADQL+qPAABf/klEQVR4nOzdC1Rc14Hm+30KJGGEZDKdjHFi2YAkwJ2eFqyeHktEdwlmel3LncSCOI7lpLsFmbvaSrslwdiOLL8AO46l2L4gKbblmZ6A+pHIeQn5kbbn9gxoLQfJ81hCPek26AEly4lxetKWJcBYgjp3733qFFWIR0GdqnNO1f9Xyy7V69QG...(32616 more characters)", "toggle": true, "type": "Header", "valid": true }
dashboard.pprint()
{ "css": "\n/* IMPORTANT: tile is a KEYWORD */\n/* It is the class of all display divs in the dashboard tabs */\n.tile {\n padding: 15px;\n margin: 17.5px;\n font-size: 1.6rem;\n}\n.nav-bar {\nfont-family: 'Source Sans Pro', Arial, sans-serif;\ncolor: #333333;\n}\n/* IMPORTANT: tile is a KEYWORD */\n/* It is the class of all display divs in the dashboard tabs */\n.header img.left-logo {\nwidth: 46px;\nheight: 46px;\n}\n.header img.right-logo {\nwidth: 46px;\nheight: 46px;\n}\n.my-style-0 {\nheight: 200px;\nbackground-color: red;\n}\n.my-style-1 {\nheight: 80px;\nbackground-color: blue;\n}\n.my-style-2 {\nheight: 100px;\nbackground-color: green;\n}\n.my-style-3 {\nheight: 60px;\nbackground-color: yellow;\n}\n.my-style-4 {\nheight: 100px;\nbackground-color: orange;\n}\n.my-style-5 {\nheight: 100px;\nbackground-color: lightpink;\n}\n.my-style-6 {\npadding: 15px;\nheight: 150px;\nbackground-color: lightblue;\n}\n.my-style-7 {\nheight: 100px;\nbackground-color: lightgray;\n}\n.my-style-8 {\nheight: 100px;\nbackground-color: purple;\n}\n.my-style-9 {\nheight: 100px;\nbackground-color: yellow;\n}\n.my-style-10 {\nheight: 120px;\nbackground-color: red;\n}\n.my-style-11 {\nheight: 240px;\nbackground-color: green;\n}\n.my-style-12 {\nheight: 1700px;\n}\n.special_row {\nborder: 2px red;\n}\n.wrapper {\nwidth: 1000px;\nmargin-top: 15px;\n}\n", "header": { "left_logo": "img/sg-logo.png", "left_logo_img_src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMcAAADHCAYAAACtBUfGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAZ7SURBVHhe7dpNqyRnGcfhqu55JYgbYTQGF+4E0UHEhQv9FApCXLgQFQ24UdxICAS/ldus/QQicSWZJDOiEDzdXd53VZ8hzMx/mfMceq7rpE53Vw+c...(2128 more characters)", "left_title": "HF-Hub", "right_logo": "img/jupyter-logo.png", "right_logo_img_src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQEAYAAADQL+qPAABf/klEQVR4nOzdC1Rc14Hm+30KJGGEZDKdjHFi2YAkwJ2eFqyeHktEdwlmel3LncSCOI7lpLsFmbvaSrslwdiOLL8AO46l2L4gKbblmZ6A+pHIeQn5kbbn9gxoLQfJ81hCPek26AEly4lxetKWJcBYgjp3733qFFWIR0GdqnNO1f9Xyy7V69QG...(32616 more characters)", "toggle": true, "type": "Header", "valid": true }, "js": [ "http://example.js" ], "latex": true, "markdown": true, "misc": { "main_class_name": "wrapper", "main_content_width": "82%", "main_nav_min_height": "15%", "main_nav_width": "17%", "main_type": "container-fluid", "no_margins": false, "type": "Misc", "valid": true }, "tabs": [ { "active": false, "elmts": [ { "size": 2, "text": "MyTitle1", "type": "Title", "valid": true }, { "elmts": { "elmts": [ { "class_name": "my-style-0", "content": "I am Block 0", "id_name": "myname-0", "is_markdown": false, "type": "Div", "valid": true, "width": 6, "with_borders": false }, { "class_name": "my-style-1", "content": "I am Block 1", "id_name": "myname-1", "is_markdown": false, "type": "Div", "valid": true, "width": 6, "with_borders": true } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true }, { "elmts": { "elmts": [ { "class_name": "my-style-2", "content": "I am Block 2", "id_name": "myname-2", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": false }, { "class_name": "my-style-3", "content": "I am Block 3", "id_name": "myname-3", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": true }, { "class_name": "my-style-4", "content": "I am Block 4", "id_name": "myname-4", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": false } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true } ], "level": 1, "name": "Tab1", "type": "Tab", "valid": true }, { "active": true, "elmts": [ { "size": 3, "text": "MyTitle2", "type": "Title", "valid": true }, { "elmts": { "elmts": [ { "class_name": "my-style-5", "content": "I am Block 5", "id_name": "myname-5", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": true }, { "class_name": "my-style-6", "content": "I am Block 6", "id_name": "myname-6", "is_markdown": false, "type": "Div", "valid": true, "width": 2, "with_borders": false } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true }, { "elmts": { "elmts": [ { "class_name": "my-style-7", "content": "I am Block 7", "id_name": "myname-7", "is_markdown": false, "type": "Div", "valid": true, "width": 8, "with_borders": true }, { "class_name": "my-style-8", "content": "I am Block 8", "id_name": "myname-8", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": false } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true } ], "level": 1, "name": "Tab2", "type": "Tab", "valid": true }, { "active": false, "elmts": [ { "active": false, "elmts": [ { "elmts": { "elmts": [ { "class_name": "my-style-0", "content": "I am Block 0", "id_name": "myname-0", "is_markdown": false, "type": "Div", "valid": true, "width": 6, "with_borders": false }, { "class_name": "my-style-1", "content": "I am Block 1", "id_name": "myname-1", "is_markdown": false, "type": "Div", "valid": true, "width": 6, "with_borders": true } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true }, { "elmts": { "elmts": [ { "class_name": "my-style-2", "content": "I am Block 2", "id_name": "myname-2", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": false }, { "class_name": "my-style-3", "content": "I am Block 3", "id_name": "myname-3", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": true }, { "class_name": "my-style-4", "content": "I am Block 4", "id_name": "myname-4", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": false } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true } ], "level": 2, "name": "MyTab31", "type": "Tab", "valid": true }, { "active": true, "elmts": [ { "elmts": { "elmts": [ { "class_name": "my-style-5", "content": "I am Block 5", "id_name": "myname-5", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": true }, { "class_name": "my-style-6", "content": "I am Block 6", "id_name": "myname-6", "is_markdown": false, "type": "Div", "valid": true, "width": 2, "with_borders": false } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true }, { "elmts": { "elmts": [ { "class_name": "my-style-7", "content": "I am Block 7", "id_name": "myname-7", "is_markdown": false, "type": "Div", "valid": true, "width": 8, "with_borders": true }, { "class_name": "my-style-8", "content": "I am Block 8", "id_name": "myname-8", "is_markdown": false, "type": "Div", "valid": true, "width": 4, "with_borders": false } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true } ], "level": 2, "name": "MyTab32", "type": "Tab", "valid": true } ], "level": 1, "name": "Rather long tab title that spans several lines", "type": "Tab", "valid": true }, { "active": false, "elmts": [ { "active": true, "elmts": [ { "size": 4, "text": "MyTitle3", "type": "Title", "valid": true }, { "class_name": "special_row", "elmts": { "elmts": [ { "class_name": "listdiv_name", "elmts": [ { "class_name": "my-style-9", "content": "I am Block 9", "id_name": "myname-9", "is_markdown": false, "type": "Div", "valid": true, "width": 12, "with_borders": true }, { "class_name": "my-style-10", "content": "I am Block 10", "id_name": "myname-10", "is_markdown": false, "type": "Div", "valid": true, "width": 12, "with_borders": false } ], "level": 2, "type": "ListDiv", "valid": true, "width": 6 }, { "class_name": "my-style-11", "content": "I am Block 11", "id_name": "myname-11", "is_markdown": false, "type": "Div", "valid": true, "width": 6, "with_borders": true } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true } ], "level": 2, "name": "MyTab41", "type": "Tab", "valid": true }, { "active": false, "elmts": [ { "size": 3, "text": "MyTitle4", "type": "Title", "valid": true }, { "elmts": { "elmts": [ { "class_name": "my-style-12", "content": "<h1>Written in Markdown</h1>\n<h2>Latex</h2>\n<p>Courtesy of <a href=\"https://www.mathjax.org/\">MathJax</a>.<br />\nYou can include mathematical expressions both inline: $ e^{i\\pi} + 1 = 0 $ and displayed as block:</p>\n<p>$$ e^x=\\sum_{i=0}^\\infty \\frac{x^i}{i!} $$</p>\n<p>To practise your Latex I recommend the <a href=\"https://www.codecogs.com/latex/eqneditor.php\">codecogs latex equation online editor</a>.</p>\n<h2>Colors</h2>\n<p>Sometimes you need to use colors to draw attention.</p>\n<p><span style=\"color:blue\">Hey <em>This is Blue italic.</em> text</span></p>\n<p><span style=\"color:red\">Hey <strong>This is Red Bold.</strong> text</span></p>\n<h2>Lists</h2>\n<ol>\n<li>First ordered list item</li>\n<li>Another item<ul>\n<li>Unordered sub-list. </li>\n</ul>\n</li>\n<li>Actual numbers don't matter, just that it's a number<ol>\n<li>Ordered sub-list</li>\n<li>Ordered sub-list other item</li>\n</ol>\n</li>\n<li>\n<p>And another item.</p>\n<p>You can have properly indented paragraphs within list items. Notice the blank line above, and the leading spaces (at least one, but we'll use three here to also align the raw Markdown).</p>\n<p>To have a line break without a paragraph, you will need to use two trailing spaces.<br />\nNote that this line is separate, but within the same paragraph.<br />\n(This is contrary to the typical GFM line break behaviour, where trailing spaces are not required.)</p>\n</li>\n</ol>\n<ul>\n<li>Unordered list can use asterisks</li>\n<li>Or minuses</li>\n<li>Or pluses</li>\n</ul>\n<h2>Tables</h2>\n<p>Tables aren't part of the core Markdown spec, but they are part of GFM and Markdown Here supports them. They are an easy way of adding tables to your email -- a task that would otherwise require copy-pasting from another application.</p>\n<p>Colons can be used to align columns.</p>\n<table>\n<thead>\n<tr>\n<th>Tables</th>\n<th align=\"center\">Are</th>\n<th align=\"right\">Cool</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>col 3 is</td>\n<td align=\"center\">right-aligned</td>\n<td align=\"right\">$1600</td>\n</tr>\n<tr>\n<td>col 2 is</td>\n<td align=\"center\">centered</td>\n<td align=\"right\">$12</td>\n</tr>\n<tr>\n<td>zebra stripes</td>\n<td align=\"center\">are neat</td>\n<td align=\"right\">$1</td>\n</tr>\n</tbody>\n</table>\n<p>There must be at least 3 dashes separating each header cell.<br />\nThe outer pipes (|) are optional, and you don't need to make the <br />\nraw Markdown line up prettily. You can also use inline Markdown.</p>\n<table>\n<thead>\n<tr>\n<th>Markdown</th>\n<th>Less</th>\n<th>Pretty</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><em>Still</em></td>\n<td><code>renders</code></td>\n<td><strong>nicely</strong></td>\n</tr>\n<tr>\n<td>1</td>\n<td>2</td>\n<td>3</td>\n</tr>\n</tbody>\n</table>", "id_name": "myname-12", "is_markdown": true, "type": "Div", "valid": true, "width": 12, "with_borders": false } ], "level": 1, "type": "ListDiv", "valid": true, "width": 12 }, "type": "Row", "valid": true } ], "level": 2, "name": "MyTab42", "type": "Tab", "valid": true } ], "level": 1, "name": "Tab4", "type": "Tab", "valid": true } ], "title": { "size": 2, "text": "MyGlobalTitle", "type": "Title", "valid": true }, "type": "Dashboard", "valid": true, "widgets": true, "widgets_state": "" }