Skip to content

Commit 35c4d07

Browse files
authored
Add a new output filter that excludes widgets if there is no state (#1643)
This allows showing a static mimetype instead of a blank widget
1 parent c663c75 commit 35c4d07

File tree

4 files changed

+88
-21
lines changed

4 files changed

+88
-21
lines changed

nbconvert/exporters/html.py

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from jinja2.loaders import split_template_path
2222

2323
from nbconvert.filters.highlight import Highlight2HTML
24+
from nbconvert.filters.widgetsdatatypefilter import WidgetsDataTypeFilter
2425
from nbconvert.filters.markdown_mistune import IPythonRenderer, MarkdownWithMath
2526

2627
from .templateexporter import TemplateExporter
@@ -98,22 +99,22 @@ def _template_name_default(self):
9899
def default_config(self):
99100
c = Config({
100101
'NbConvertBase': {
101-
'display_data_priority' : ['application/vnd.jupyter.widget-state+json',
102-
'application/vnd.jupyter.widget-view+json',
103-
'application/javascript',
104-
'text/html',
105-
'text/markdown',
106-
'image/svg+xml',
107-
'text/latex',
108-
'image/png',
109-
'image/jpeg',
110-
'text/plain'
111-
]
112-
},
102+
'display_data_priority': [
103+
'application/vnd.jupyter.widget-view+json',
104+
'application/javascript',
105+
'text/html',
106+
'text/markdown',
107+
'image/svg+xml',
108+
'text/latex',
109+
'image/png',
110+
'image/jpeg',
111+
'text/plain'
112+
]
113+
},
113114
'HighlightMagicsPreprocessor': {
114-
'enabled':True
115-
}
116-
})
115+
'enabled': True
116+
}
117+
})
117118
c.merge(super().default_config)
118119
return c
119120

@@ -136,7 +137,10 @@ def from_notebook_node(self, nb, resources=None, **kw):
136137
langinfo = nb.metadata.get('language_info', {})
137138
lexer = langinfo.get('pygments_lexer', langinfo.get('name', None))
138139
highlight_code = self.filters.get('highlight_code', Highlight2HTML(pygments_lexer=lexer, parent=self))
140+
filter_data_type = WidgetsDataTypeFilter(notebook_metadata=nb.metadata, parent=self)
141+
139142
self.register_filter('highlight_code', highlight_code)
143+
self.register_filter('filter_data_type', filter_data_type)
140144
return super().from_notebook_node(nb, resources, **kw)
141145

142146
def _init_resources(self, resources):
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""Filter used to select the first preferred output format available,
2+
excluding interactive widget format if the widget state is not available.
3+
4+
The filter contained in the file allows the converter templates to select
5+
the output format that is most valuable to the active export format. The
6+
value of the different formats is set via
7+
NbConvertBase.display_data_priority
8+
"""
9+
#-----------------------------------------------------------------------------
10+
# Copyright (c) 2013, the IPython Development Team.
11+
#
12+
# Distributed under the terms of the Modified BSD License.
13+
#
14+
# The full license is in the file COPYING.txt, distributed with this software.
15+
#-----------------------------------------------------------------------------
16+
17+
#-----------------------------------------------------------------------------
18+
# Classes and functions
19+
#-----------------------------------------------------------------------------
20+
21+
from warnings import warn
22+
23+
from ..utils.base import NbConvertBase
24+
25+
__all__ = ['WidgetsDataTypeFilter']
26+
27+
28+
WIDGET_VIEW_MIMETYPE = 'application/vnd.jupyter.widget-view+json'
29+
WIDGET_STATE_MIMETYPE = 'application/vnd.jupyter.widget-state+json'
30+
31+
32+
class WidgetsDataTypeFilter(NbConvertBase):
33+
""" Returns the preferred display format, excluding the widget output if
34+
there is no widget state available """
35+
36+
def __init__(self, notebook_metadata=None, **kwargs):
37+
metadata = notebook_metadata or {}
38+
39+
self.widgets_state = (
40+
metadata['widgets'][WIDGET_STATE_MIMETYPE]['state'] if
41+
metadata.get('widgets') is not None else {}
42+
)
43+
44+
super().__init__(**kwargs)
45+
46+
def __call__(self, output):
47+
""" Return the first available format in the priority.
48+
49+
Produces a UserWarning if no compatible mimetype is found.
50+
51+
`output` is dict with structure {mimetype-of-element: value-of-element}
52+
53+
"""
54+
for fmt in self.display_data_priority:
55+
if fmt in output:
56+
# If there is no widget state available, we skip this mimetype
57+
if (
58+
fmt == WIDGET_VIEW_MIMETYPE and
59+
output[WIDGET_VIEW_MIMETYPE]['model_id'] not in self.widgets_state
60+
):
61+
continue
62+
63+
return [fmt]
64+
warn("Your element with mimetype(s) {mimetypes}"
65+
" is not able to be represented.".format(
66+
mimetypes=output.keys())
67+
)
68+
69+
return []

share/jupyter/nbconvert/templates/base/display_priority.j2

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@
3232
{%- elif type == 'application/javascript' -%}
3333
{%- block data_javascript -%}
3434
{%- endblock -%}
35-
{%- elif type == 'application/vnd.jupyter.widget-state+json' -%}
36-
{%- block data_widget_state -%}
37-
{%- endblock -%}
3835
{%- elif type == 'application/vnd.jupyter.widget-view+json' -%}
3936
{%- block data_widget_view -%}
4037
{%- endblock -%}

share/jupyter/nbconvert/templates/latex/display_priority.j2

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,6 @@
3636
((*- elif type == 'application/javascript' -*))
3737
((*- block data_javascript -*))
3838
((*- endblock -*))
39-
((*- elif type == 'application/vnd.jupyter.widget-state+json' -*))
40-
((*- block data_widget_state -*))
41-
((*- endblock -*))
4239
((*- elif type == 'application/vnd.jupyter.widget-view+json' -*))
4340
((*- block data_widget_view -*))
4441
((*- endblock -*))

0 commit comments

Comments
 (0)