The original flexbox doesn't embed trivially because of widgets. This notebook creates the basic infrastructure to compose html representations of rich display objects in flexboxes.
from IPython.display import *
import mimetypes
from graphviz import Source
from mistune import markdown
from dataclasses import dataclass
html_shortcuts = 'nbviewer', 'wiki'
def html(type, src_=None, **kwargs):
kwargs['width'], kwargs['height'] = kwargs.get('width', 500), kwargs.get('height', 450)
return IFrame(kwargs.pop('src', src_), **kwargs)
def image(type, url_=None, **kwargs):
assert type.startswith('image')
if kwargs.get('url', url_): kwargs['url'] = kwargs.get('url', url_)
if 'svg' in type: return HTML(**kwargs)
return Image(**kwargs)
def youtube(type, id_=None, **kwargs):
if kwargs.get('id', id_): kwargs['id'] = kwargs.get('id', id_)
return YouTubeVideo(**kwargs)
def other(type, str, **kwargs):
if str.split()[0] in {'graph', 'digraph'}: return HTML(Source(str, format='svg')._repr_svg_())
return HTML(markdown(str, escape=False))
object_to_display
will infer the mimetypes that must be displayed.
def object_to_display(object):
if not isinstance(object, dict):
type = mimetypes.guess_type(object)[0]
if not type:
for shortcut in html_shortcuts:
if shortcut in object: type = 'text/html'
else: type, object = next(iter(object.items()))
if isinstance(object, dict): arg = None
else: arg, object = object, {}
if type:
if any(object in type for object in ('html', 'pdf')): return html(type, arg, **object)
elif 'image' in type: return image(type, arg, **object)
elif ('youtube' in type) or ('youtube' in object): return youtube(type, arg, **object)
return other(type, arg, **object)
def display_to_string(object):
try:
html = object._repr_html_()
if html: return object._repr_html_()
except: return f"""<img src="data:image/{object.format};base64,{getattr(object, '_repr_'+object.format+'_')()}"/>
""" if isinstance(object, Image) else ""
class inverse(__import__('abc').ABCMeta):
def __invert__(cls): return cls is Column and Row or Column
@dataclass
class Column(metaclass=inverse):
content: None = None
def _repr_html_(self, order=0):
if isinstance(self.content, list):
return self.block.format(''.join(
(~type(self))(object)._repr_html_() for object in self.content))
if isinstance(self.content, dict):
order = self.content.pop('order', order)
return """<div class="flexed-item" style="order: {};">{}</div>""".format(order, display_to_string(object_to_display(self.content)))
def __invert__(self): return (~type(self))(**vars(self))
@property
def block(self): return f"""<div class="flexed-container flexed-{type(self).__name__.lower()}">{"{}"}</div>"""
@dataclass
class Row(Column): ...
from IPython import get_ipython
display(HTML("""
<style>
.flexed-container {display: flex; margin: 30px;}
.flexed-container.flexed-row {flex-direction: row;}
.flexed-container.flexed-column {flex-direction: column;}
.flexed-container iframe {min-width: 350px;}
.flexed-item {order: 0; margin: 20px;}
</style>"""))
from pytest import fixture
from deathbeds.__Flexbox_Transformer import FlexBoxTransformer as PreviousTransformer
class FlexBoxTransformer(PreviousTransformer):
condition = staticmethod(lambda str: str.lstrip().startswith('- ') or str.lstrip().startswith('['))
replacement = """__import__('IPython').display.display(
__import__('importlib').import_module('deathbeds.2018-08-16-HTML-Flexbox').Row(__import__('yaml').safe_load({}))
)"""
def load_ipython_extension(ip): ip.ast_transformers.append(FlexBoxTransformer())
def unload_ipython_extension(ip): ip.ast_transformers = [object for object in ip.ast_transformers if isinstance(object, FlexBoxTransformer)]
@fixture
def ip(): ip = __import__('IPython').get_ipython(); load_ipython_extension(ip); yield ip; unload_ipython_extension(ip)
class example:
"""
- <img src="data/IMG-0762.JPG" width="200"/>
- - <img src="data/IMG-0762.JPG" width="200"/>
- <img src="data/IMG-0762.JPG" width="200"/>
- - Test
- graph {layout=circo a--b--c--a}
- Test
- <img src="data/IMG-0762.JPG" width="200"/>
- <img src="data/IMG-0762.JPG" width="400"/>
"""; """
- data/IMG-0762.JPG
"""
F"{example.__doc__}"
Test
Test
def _autoflexing(ip):
import yaml , io
ip.run_cell("""'''{}'''""".format(example.__doc__))