Whilst trying to create IFrame generating magics to embded content in Jupyter Book output, I noticed that the IPython.display.IFrame
element only appears to let you refer to external src
linked HTML content and not inline/embedded srcdata
content. This has the downside that you need to find a way ofcopying any generated src
-linked HTML page into the Jupyter Book / sphinx generated distribution directory (Sphinx/Jupyter Book doesn’t seem to copy linked local pages over (I think bookdown
publishing workflow does?).
Noting that folium
maps render okay in Jupyter Book without manual copyting of the map containing HTML file, I had a peek at the source code and noticed it was using embedded srcdata
content.
Cribbing the mechanics, the following approach can be used to create an object with a __rep_html__
method that returns an IFrame with embedded srcdoc
content that will render the content in Jupyter Book output without the need for an externally linked src
file. The HTML is generated from a template page (template
) populated using named template attributes passed via a Python dict
( data
). Once the object is created, when used as the last item in a notebook code cell it will return the inlined-IFrame as the display object.
from html import escape
from IPython.display import IFrame
class myDisplayObject:
def __init__(self, data, template, width="100%", height=None, ratio=1):
self.width = width
self.height = height
self.ratio = ratio
self.html = self.js_html(data, template)
def js_html(self, data, template):
"""Generate the HTML for the js diagram."""
return template.format(**data)
# cribbed from branca Py package
def _repr_html_(self, **kwargs):
"""Displays the Diagram in a Jupyter notebook."""
html = escape(self.html)
if self.height is None:
iframe = (
'<div style="width:{width};">'
'<div style="position:relative;width:100%;height:0;padding-bottom:{ratio};">' # noqa
'<span style="color:#565656">Make this Notebook Trusted to load map: File -> Trust Notebook</span>' # noqa
'<iframe srcdoc="{html}" style="position:absolute;width:100%;height:100%;left:0;top:0;' # noqa
'border:none !important;" '
'allowfullscreen webkitallowfullscreen mozallowfullscreen>'
'</iframe>'
'</div></div>'
).format(html=html, width=self.width, ratio=self.ratio)
else:
iframe = (
'<iframe srcdoc="{html}" width="{width}" height="{height}"'
'style="border:none !important;" '
'"allowfullscreen" "webkitallowfullscreen" "mozallowfullscreen">'
'</iframe>'
).format(html=html, width=self.width, height=self.height)
return iframe
For an example of how this is used, see innovationOUtside/nb_js_diagrammers
(functionality added via this commit).