I’m using sphinx-gallery to generate example documentation as .ipynb files that are generated from .py files. My code uses panel with tabulator and plotly. When the documentation is generated, the tables and plots are missing. I’ve looked at Embedding in Sphinx documentation — Panel v1.2.2 but it doesn’t seem to address my needs as I don’t have an .rst file. Am I misinterpreting Embedding in Sphinx documentation — Panel v1.2.2? Or, is a scraper available for panel that I can use in my spinx conf.py file? I don’t need my example files to be interactive, they can show static images of the tables and plots.
Hi @pkrull
Welcome to the community. I’ve never used sphinx-gallery
. But here is some exploration.
When asking for help please always provide a minimum, reproducible example as a starting point. If you have a specialized problem (as you do) there will not be a lot of people having experience with your problem. But if you provide something that makes it easy to to get started then its easier for the Panel community to work with the problem.
Here is a minimum, reproducible example sphinx-gallery-panel-example
The main problem is that Panel objects do not seem to have a _repr_html_
method. So Sphinx-Gallery will just output the string representation.
What I’ve done so far is to add a _repr_html_
method in the sphinx conf.py
.
# Configure sphinx-gallery for panel
import panel as pn
from uuid import uuid4
from io import StringIO
from html import escape
import param
class PanelReprHTML(param.Parameterized):
max_height=param.Integer(1000, bounds=(0,None))
embed = param.Boolean(True)
def __init__(self, object):
self._object = object
def _get_html(self):
out = StringIO()
self._object.save(out, embed=self.embed)
out.seek(0)
return escape(out.read())
def _repr_html_(self):
html = self._get_html()
uid = str(uuid4())
return f"""
<script>
function resizeIframe(){{
setTimeout(() => {{
var iframe = document.getElementById("{uid}");
iframe.width = iframe.contentWindow.document.body.scrollWidth + 25;
iframe.height = Math.min(iframe.contentWindow.document.body.scrollHeight + 10, {self.max_height});
console.log(iframe.height)
}}, "100");
}}
</script>
<iframe id="{uid}" srcdoc='{html}' frameBorder='0' onload='resizeIframe(this)'></iframe>
"""
def _repr_html_(self):
return PanelReprHTML(self)._repr_html_()
def add_repr_html():
pn.viewable.Viewable._repr_html_=_repr_html_
PanelReprHTML.max_height=600
add_repr_html()
And it works!
I’ve made a feature request for Panel and will continue the discussion there.
Make it easy to use Panel with Sphinx-Gallery · Issue #5519 · holoviz/panel (github.com)
@Marc, I really appreciate this prototype!!! I would have never thought of the approach you took. It’s great! You’ve saved me many hours!!!
One limitation I’ve found is, I’m using multiple controls with my plots and the callbacks for the controls don’t seem to get called. Maybe I’m missing a dependency but I don’t see an error in the browser console when I select the control. For instance, I use some MultiSelect controls to filter a Tabulator table. When I select an item from one of the MultiSelects, the Tabulator table doesn’t update. I consider this a minor inconvenience.
Again, many thanks for your contribution!
Thanks @pkrull
The current approach creates static output, you will not get live interactivity. To get interactivity you would need to extend the approach by
.embed
. This can work nicely if you component has a limited number of states.- Use pyoide. My guess is that inspiration can be found here Embedding in Sphinx documentation
- Use a live server in the backend