diff --git a/nbconvert/exporters/html.py b/nbconvert/exporters/html.py
index 65b93702e..9f02b774c 100644
--- a/nbconvert/exporters/html.py
+++ b/nbconvert/exporters/html.py
@@ -21,6 +21,7 @@
from jinja2.loaders import split_template_path
from nbconvert.filters.highlight import Highlight2HTML
+from nbconvert.filters.widgetsdatatypefilter import WidgetsDataTypeFilter
from nbconvert.filters.markdown_mistune import IPythonRenderer, MarkdownWithMath
from .templateexporter import TemplateExporter
@@ -98,22 +99,22 @@ def _template_name_default(self):
def default_config(self):
c = Config({
'NbConvertBase': {
- 'display_data_priority' : ['application/vnd.jupyter.widget-state+json',
- 'application/vnd.jupyter.widget-view+json',
- 'application/javascript',
- 'text/html',
- 'text/markdown',
- 'image/svg+xml',
- 'text/latex',
- 'image/png',
- 'image/jpeg',
- 'text/plain'
- ]
- },
+ 'display_data_priority': [
+ 'application/vnd.jupyter.widget-view+json',
+ 'application/javascript',
+ 'text/html',
+ 'text/markdown',
+ 'image/svg+xml',
+ 'text/latex',
+ 'image/png',
+ 'image/jpeg',
+ 'text/plain'
+ ]
+ },
'HighlightMagicsPreprocessor': {
- 'enabled':True
- }
- })
+ 'enabled': True
+ }
+ })
c.merge(super().default_config)
return c
@@ -136,7 +137,10 @@ def from_notebook_node(self, nb, resources=None, **kw):
langinfo = nb.metadata.get('language_info', {})
lexer = langinfo.get('pygments_lexer', langinfo.get('name', None))
highlight_code = self.filters.get('highlight_code', Highlight2HTML(pygments_lexer=lexer, parent=self))
+ filter_data_type = WidgetsDataTypeFilter(notebook_metadata=nb.metadata, parent=self)
+
self.register_filter('highlight_code', highlight_code)
+ self.register_filter('filter_data_type', filter_data_type)
return super().from_notebook_node(nb, resources, **kw)
def _init_resources(self, resources):
diff --git a/nbconvert/filters/widgetsdatatypefilter.py b/nbconvert/filters/widgetsdatatypefilter.py
new file mode 100644
index 000000000..6d390b44e
--- /dev/null
+++ b/nbconvert/filters/widgetsdatatypefilter.py
@@ -0,0 +1,69 @@
+"""Filter used to select the first preferred output format available,
+excluding interactive widget format if the widget state is not available.
+
+The filter contained in the file allows the converter templates to select
+the output format that is most valuable to the active export format. The
+value of the different formats is set via
+NbConvertBase.display_data_priority
+"""
+#-----------------------------------------------------------------------------
+# Copyright (c) 2013, the IPython Development Team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file COPYING.txt, distributed with this software.
+#-----------------------------------------------------------------------------
+
+#-----------------------------------------------------------------------------
+# Classes and functions
+#-----------------------------------------------------------------------------
+
+from warnings import warn
+
+from ..utils.base import NbConvertBase
+
+__all__ = ['WidgetsDataTypeFilter']
+
+
+WIDGET_VIEW_MIMETYPE = 'application/vnd.jupyter.widget-view+json'
+WIDGET_STATE_MIMETYPE = 'application/vnd.jupyter.widget-state+json'
+
+
+class WidgetsDataTypeFilter(NbConvertBase):
+ """ Returns the preferred display format, excluding the widget output if
+ there is no widget state available """
+
+ def __init__(self, notebook_metadata=None, **kwargs):
+ metadata = notebook_metadata or {}
+
+ self.widgets_state = (
+ metadata['widgets'][WIDGET_STATE_MIMETYPE]['state'] if
+ metadata.get('widgets') is not None else {}
+ )
+
+ super().__init__(**kwargs)
+
+ def __call__(self, output):
+ """ Return the first available format in the priority.
+
+ Produces a UserWarning if no compatible mimetype is found.
+
+ `output` is dict with structure {mimetype-of-element: value-of-element}
+
+ """
+ for fmt in self.display_data_priority:
+ if fmt in output:
+ # If there is no widget state available, we skip this mimetype
+ if (
+ fmt == WIDGET_VIEW_MIMETYPE and
+ output[WIDGET_VIEW_MIMETYPE]['model_id'] not in self.widgets_state
+ ):
+ continue
+
+ return [fmt]
+ warn("Your element with mimetype(s) {mimetypes}"
+ " is not able to be represented.".format(
+ mimetypes=output.keys())
+ )
+
+ return []
diff --git a/share/jupyter/nbconvert/templates/base/display_priority.j2 b/share/jupyter/nbconvert/templates/base/display_priority.j2
index 56ad7cde7..ee4987fc2 100644
--- a/share/jupyter/nbconvert/templates/base/display_priority.j2
+++ b/share/jupyter/nbconvert/templates/base/display_priority.j2
@@ -32,9 +32,6 @@
{%- elif type == 'application/javascript' -%}
{%- block data_javascript -%}
{%- endblock -%}
- {%- elif type == 'application/vnd.jupyter.widget-state+json' -%}
- {%- block data_widget_state -%}
- {%- endblock -%}
{%- elif type == 'application/vnd.jupyter.widget-view+json' -%}
{%- block data_widget_view -%}
{%- endblock -%}
diff --git a/share/jupyter/nbconvert/templates/latex/display_priority.j2 b/share/jupyter/nbconvert/templates/latex/display_priority.j2
index 9f33a74e1..c97736ec8 100644
--- a/share/jupyter/nbconvert/templates/latex/display_priority.j2
+++ b/share/jupyter/nbconvert/templates/latex/display_priority.j2
@@ -36,9 +36,6 @@
((*- elif type == 'application/javascript' -*))
((*- block data_javascript -*))
((*- endblock -*))
- ((*- elif type == 'application/vnd.jupyter.widget-state+json' -*))
- ((*- block data_widget_state -*))
- ((*- endblock -*))
((*- elif type == 'application/vnd.jupyter.widget-view+json' -*))
((*- block data_widget_view -*))
((*- endblock -*))