(Worked out for an aspect of SO answer https://stackoverflow.com/a/78674203/8508004.)
The proposed example, shown below only required proper rendering of a couple of features of markdown:
#based on https://stackoverflow.com/q/78670150/8508004, and adapting to put matplotlib in a widget from https://stackoverflow.com/a/51060721/8508004 (which I think was adapted in some ways from https://github.com/jupyter-widgets/ipywidgets/issues/2821)
from ipywidgets import widgets, Layout
from IPython.display import display, Javascript, Markdown as md
import numpy as np
import matplotlib.pyplot as plt
left_widget = widgets.Output()
def func(x, a, b, c, d):
return a + b*np.exp(c*x + d)
the_x = np.arange(0, 10, 0.5)
the_y = func(the_x, 1, 1, -1, 2)
with left_widget:
fig, ax = plt.subplots()
ax.plot(the_x, the_y)
plt.show(fig)
len_x = len(the_x)
mdout = md(f"""There are {len_x} **elements** of both `the_x`, and `the_y`;
Those values are plotted on the diagram on the left""")
box_layout = Layout(display='flex',
flex_flow='row',
justify_content='space-around',
width='auto'
)
hbox1 = widgets.Box(children=[left_widget, widgets.HTML(mdout._repr_markdown_())], layout=box_layout)
display(hbox1)
Namely, bold items flanked by double asterisks and highlight as code text flanked by a backtick.
However, because bold indication by double asterisks seems problematic, I added a third example to better illustrate some of markdown rendering is handled adequetely without special measures.
The third example added is section heading handling.
That gives as the real starting point for much of what is covered here:
#based on https://stackoverflow.com/q/78670150/8508004, and adapting to put matplotlib in a widget from https://stackoverflow.com/a/51060721/8508004 (which I think was adapted in some ways from https://github.com/jupyter-widgets/ipywidgets/issues/2821)
from ipywidgets import widgets, Layout
from IPython.display import display, Javascript, Markdown as md
import numpy as np
import matplotlib.pyplot as plt
left_widget = widgets.Output()
def func(x, a, b, c, d):
return a + b*np.exp(c*x + d)
the_x = np.arange(0, 10, 0.5)
the_y = func(the_x, 1, 1, -1, 2)
with left_widget:
fig, ax = plt.subplots()
ax.plot(the_x, the_y)
plt.show(fig)
len_x = len(the_x)
md_content = f"""# (Markdown Heading Rendered) RESULTS:
There are {len_x} **elements** of both `the_x`, and `the_y`;
Those values are plotted on the diagram on the left"""
box_layout = Layout(display='flex',
flex_flow='row',
justify_content='space-around',
width='auto'
)
hbox1 = widgets.Box(children=[left_widget, widgets.HTML(mdout._repr_markdown_())], layout=box_layout)
display(hbox1)
#based on https://stackoverflow.com/q/78670150/8508004, and adapting to put matplotlib in a widget from https://stackoverflow.com/a/51060721/8508004 (which I think was adapted in some ways from https://github.com/jupyter-widgets/ipywidgets/issues/2821)
from ipywidgets import widgets, Layout, HTML
from IPython.display import display
import numpy as np
import matplotlib.pyplot as plt
import markdown
left_widget = widgets.Output()
def func(x, a, b, c, d):
return a + b*np.exp(c*x + d)
the_x = np.arange(0, 10, 0.5)
the_y = func(the_x, 1, 1, -1, 2)
with left_widget:
fig, ax = plt.subplots()
ax.plot(the_x, the_y)
plt.show(fig)
len_x = len(the_x)
md_content = f"""# (Markdown Heading Rendered) RESULTS:
There are {len_x} **elements** of both `the_x`, and `the_y`;
Those values are plotted on the diagram on the left"""
box_layout = Layout(display='flex',
flex_flow='row',
justify_content='space-around',
width='auto'
)
html_content = markdown.markdown(md_content)
markdown_widget = widgets.HTML(
value=f"""
<style>
.markdown-body {{
font-family: Arial, sans-serif;
padding: 10px;
}}
.markdown-body code {{
background-color: #f0f0f0;
padding: 2px 4px;
border-radius: 3px;
}}
</style>
<div class="markdown-body">
{html_content}
</div>
"""
)
hbox1 = widgets.Box(children=[left_widget, markdown_widget], layout=box_layout)
display(hbox1)
Box(children=(Output(), HTML(value='\n <style>\n .markdown-body {\n font-family: Arial, sans-seri…
How did I get there?
That is covered below step-by-step, but here are some alternatives. The step-by-step will cover those, too. And why simpler adaptations may be all you need.
with markdown2
#based on https://stackoverflow.com/q/78670150/8508004, and adapting to put matplotlib in a widget from https://stackoverflow.com/a/51060721/8508004 (which I think was adapted in some ways from https://github.com/jupyter-widgets/ipywidgets/issues/2821)
from ipywidgets import widgets, Layout
import numpy as np
import matplotlib.pyplot as plt
import markdown2
left_widget = widgets.Output()
def func(x, a, b, c, d):
return a + b*np.exp(c*x + d)
the_x = np.arange(0, 10, 0.5)
the_y = func(the_x, 1, 1, -1, 2)
with left_widget:
fig, ax = plt.subplots()
ax.plot(the_x, the_y)
plt.show(fig)
len_x = len(the_x)
md_content = f"""# (Markdown Heading Rendered) RESULTS:
There are {len_x} **elements** of both `the_x`, and `the_y`;
Those values are plotted on the diagram on the left"""
box_layout = Layout(display='flex',
flex_flow='row',
justify_content='space-around',
width='auto'
)
html_content = markdown2.markdown(md_content)
markdown_widget = widgets.HTML(
value=f"""
<style>
.markdown-body {{
font-family: Arial, sans-serif;
padding: 10px;
}}
.markdown-body code {{
background-color: #f0f0f0;
padding: 2px 4px;
border-radius: 3px;
}}
</style>
<div class="markdown-body">
{html_content}
</div>
"""
)
hbox1 = widgets.Box(children=[left_widget, markdown_widget], layout=box_layout)
display(hbox1)
Box(children=(Output(), HTML(value='\n <style>\n .markdown-body {\n font-family: Arial, sans-seri…
There's actually a third alternative presented at the bottom of this document suggesting converting the markdown feature calls to HTML directly and using CSS for full-featured control of the styling.
markdown2
use¶Note these SEPARATE solutions need to be tested in separate fresh sessions so that the CSS used isn't working behind-the-scenes and misleading as to what is working or not.
Starting with our starting point that has section heading, we'll drop the line from IPython.display import display, Javascript, Markdown as md
and add in markdown2
use to convert Markdown syntax into HTML. (This happened to be where I started but it turns out markdown
is fine for this, it seems, too. See below.) This conversion is necessary because the markdown text inside an ipywidget HTML widget doesn't get converted automatically like markdown does in a markdown cell in Jupyter, a markdown cell being able to handle markdown and HTML out of the box.
You'll most likely need to install that markdown2 package to use it. Install it from within the running Juyter notebooks with either %conda install -c conda-forge markdown2
or %pip install markdown2
.
#based on https://stackoverflow.com/q/78670150/8508004, and adapting to put matplotlib in a widget from https://stackoverflow.com/a/51060721/8508004 (which I think was adapted in some ways from https://github.com/jupyter-widgets/ipywidgets/issues/2821)
from ipywidgets import widgets, Layout
import numpy as np
import matplotlib.pyplot as plt
import markdown2
left_widget = widgets.Output()
def func(x, a, b, c, d):
return a + b*np.exp(c*x + d)
the_x = np.arange(0, 10, 0.5)
the_y = func(the_x, 1, 1, -1, 2)
with left_widget:
fig, ax = plt.subplots()
ax.plot(the_x, the_y)
plt.show(fig)
len_x = len(the_x)
md_content = f"""# (Markdown Heading Rendered) RESULTS:
There are {len_x} **elements** of both `the_x`, and `the_y`;
Those values are plotted on the diagram on the left"""
box_layout = Layout(display='flex',
flex_flow='row',
justify_content='space-around',
width='auto'
)
html_content = markdown2.markdown(md_content)
hbox1 = widgets.Box(children=[left_widget, widgets.HTML(html_content)], layout=box_layout)
display(hbox1)
Box(children=(Output(), HTML(value='<h1>(Markdown Heading Rendered) RESULTS:</h1>\n\n<p>There are 20 <strong>e…
That use of markdown2
to convert the string with the content to put in the HTML widget gets us most of the way there.
However, the code highlighting in between the ticks isn't rendered. I don't know why that specification isn't handled right, but a workaround that works is is to add the styling to the HTML with custom CSS styling and then that feature also renders correctly. This is because the HTML widget doesn't automatically inherit all the default styles that would normally be applied to HTML in a Jupyter markdown cell.
#based on https://stackoverflow.com/q/78670150/8508004, and adapting to put matplotlib in a widget from https://stackoverflow.com/a/51060721/8508004 (which I think was adapted in some ways from https://github.com/jupyter-widgets/ipywidgets/issues/2821)
from ipywidgets import widgets, Layout, HTML
import numpy as np
import matplotlib.pyplot as plt
import markdown2
left_widget = widgets.Output()
def func(x, a, b, c, d):
return a + b*np.exp(c*x + d)
the_x = np.arange(0, 10, 0.5)
the_y = func(the_x, 1, 1, -1, 2)
with left_widget:
fig, ax = plt.subplots()
ax.plot(the_x, the_y)
plt.show(fig)
len_x = len(the_x)
md_content = f"""# (Markdown Heading Rendered) RESULTS:
There are {len_x} **elements** of both `the_x`, and `the_y`;
Those values are plotted on the diagram on the left"""
box_layout = Layout(display='flex',
flex_flow='row',
justify_content='space-around',
width='auto'
)
html_content = markdown2.markdown(md_content)
markdown_widget = HTML(
value=f"""
<style>
.markdown-body {{
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
font-size: 16px;
line-height: 1.5;
word-wrap: break-word;
}}
.markdown-body code {{
padding: .2em .4em;
margin: 0;
font-size: 85%;
background-color: rgba(27,31,35,.05);
border-radius: 3px;
}}
</style>
<div class="markdown-body">
{html_content}
</div>
"""
)
hbox1 = widgets.Box(children=[left_widget, markdown_widget], layout=box_layout)
display(hbox1)
Box(children=(Output(), HTML(value='\n <style>\n .markdown-body {\n font-family: -apple-system,Bl…
There everything is rendered as markdown well in the right side of the output.
Note that if I didn't care about using ticks to indicate code highlighting, I pretty much could have used markdown2
to convert the markdown text to HTML and been done. I wouldn't have needed to wrap the HTML content in CSS control if that had been the case.
markdown
can work as well¶Note these SEPARATE solutions need to be tested in separate fresh sessions so that the CSS used isn't working behind-the-scenes and misleading as to what is working or not.
markdown
can work, too, for the conversion of Markdown syntax into HTML.
We'll go back to the starting point from the top of this document and add in markdown
for the conversion of the text to HTML.
#based on https://stackoverflow.com/q/78670150/8508004, and adapting to put matplotlib in a widget from https://stackoverflow.com/a/51060721/8508004 (which I think was adapted in some ways from https://github.com/jupyter-widgets/ipywidgets/issues/2821)
from ipywidgets import widgets, Layout
import numpy as np
import matplotlib.pyplot as plt
import markdown
left_widget = widgets.Output()
def func(x, a, b, c, d):
return a + b*np.exp(c*x + d)
the_x = np.arange(0, 10, 0.5)
the_y = func(the_x, 1, 1, -1, 2)
with left_widget:
fig, ax = plt.subplots()
ax.plot(the_x, the_y)
plt.show(fig)
len_x = len(the_x)
md_content = f"""# (Markdown Heading Rendered) RESULTS:
There are {len_x} **elements** of both `the_x`, and `the_y`;
Those values are plotted on the diagram on the left"""
box_layout = Layout(display='flex',
flex_flow='row',
justify_content='space-around',
width='auto'
)
html_content = markdown.markdown(md_content)
hbox1 = widgets.Box(children=[left_widget, widgets.HTML(html_content)], layout=box_layout)
display(hbox1)
Box(children=(Output(), HTML(value='<h1>(Markdown Heading Rendered) RESULTS:</h1>\n<p>There are 20 <strong>ele…
Just as above, the use of markdown
to convert the string with the content to put in the HTML widget gets us most of the way there.
However, the code in between the ticks isn't getting rendered as 'code' styling. Again, we can use the workaround of adding the CSS styling to wrap the HTML and then that feature also renders correctly.
#based on https://stackoverflow.com/q/78670150/8508004, and adapting to put matplotlib in a widget from https://stackoverflow.com/a/51060721/8508004 (which I think was adapted in some ways from https://github.com/jupyter-widgets/ipywidgets/issues/2821)
from ipywidgets import widgets, Layout, HTML
import numpy as np
import matplotlib.pyplot as plt
import markdown
left_widget = widgets.Output()
def func(x, a, b, c, d):
return a + b*np.exp(c*x + d)
the_x = np.arange(0, 10, 0.5)
the_y = func(the_x, 1, 1, -1, 2)
with left_widget:
fig, ax = plt.subplots()
ax.plot(the_x, the_y)
plt.show(fig)
len_x = len(the_x)
md_content = f"""# (Markdown Heading Rendered) RESULTS:
There are {len_x} **elements** of both `the_x`, and `the_y`;
Those values are plotted on the diagram on the left"""
box_layout = Layout(display='flex',
flex_flow='row',
justify_content='space-around',
width='auto'
)
html_content = markdown.markdown(md_content)
markdown_widget = widgets.HTML(
value=f"""
<style>
.markdown-body {{
font-family: Arial, sans-serif;
padding: 10px;
}}
.markdown-body code {{
background-color: #f0f0f0;
padding: 2px 4px;
border-radius: 3px;
}}
</style>
<div class="markdown-body">
{html_content}
</div>
"""
)
html_content = markdown.markdown(md_content)
hbox1 = widgets.Box(children=[left_widget, markdown_widget], layout=box_layout)
display(hbox1)
Box(children=(Output(), HTML(value='\n <style>\n .markdown-body {\n font-family: Arial, sans-seri…
As with above:
Note that if I didn't care about using double asterisks to indicate bold, I pretty much could have used markdown
to convert the markdown text to HTML and been done. I wouldn't have needed to wrap the HTML content in CSS control if that had been the case.
Finally, if we go back to considering the original code with no section headings involved, you can have full control over all elements with using HTML & CSS for all. This type of approach can allow fine grain control if markdown
or markdown2
isn't covering it.
from ipywidgets import widgets, Layout
#from IPython.display import display, Javascript, Markdown as md
import numpy as np
import matplotlib.pyplot as plt
left_widget = widgets.Output()
def func(x, a, b, c, d):
return a + b*np.exp(c*x + d)
the_x = np.arange(0, 10, 0.5)
the_y = func(the_x, 1, 1, -1, 2)
with left_widget:
fig, ax = plt.subplots()
ax.plot(the_x, the_y)
plt.show(fig)
len_x = len(the_x)
md_content = f"""There are {len_x} **elements** of both `the_x`, and `the_y`;
Those values are plotted on the diagram on the left"""
box_layout = Layout(display='flex',
flex_flow='row',
justify_content='space-around',
width='auto'
)
def simple_markdown_to_html(text):
# Handle bold text
text = text.replace('**', '<strong>', 1).replace('**', '</strong>', 1)
# Handle inline code
while '`' in text:
text = text.replace('`', '<code>', 1).replace('`', '</code>', 1)
return text
html_content = simple_markdown_to_html(md_content)
markdown_widget = widgets.HTML(
value=f"""
<style>
.markdown-body {{
font-family: Arial, sans-serif;
padding: 10px;
}}
.markdown-body strong {{
font-weight: bold;
}}
.markdown-body code {{
background-color: #f0f0f0;
padding: 2px 4px;
border-radius: 3px;
font-family: monospace;
}}
</style>
<div class="markdown-body">
{html_content}
</div>
"""
)
hbox1 = widgets.Box(children=[left_widget, markdown_widget], layout=box_layout)
display(hbox1)
Box(children=(Output(), HTML(value='\n <style>\n .markdown-body {\n font-family: Arial, sans-seri…