spatialaudio / nbsphinx

:ledger: Sphinx source parser for Jupyter notebooks
https://nbsphinx.readthedocs.io/
MIT License
457 stars 130 forks source link

Widget, requirejs - troublesome again #519

Closed fcollonval closed 3 years ago

fcollonval commented 3 years ago

Jupyter widget provides a nice cookiecutter template that provide a template for generating documentation. The template preloads jupyter-sphinx and nbsphinx. But if you drop jupyter-sphinx, the widgets are not renderer (i did not found a workaround). And if you keep it the widgets are rendered twice (this can be fixed xref #378).

jupyter-sphinx is needed because when activating the two extensions (and applying #378), the JS scripts order is (using https://osscar-docs.readthedocs.io/en/latest/widgets/periodictable.html):

image

The trouble is the JS ordering (again :sob: ):

  1. Libraries from jupyter-sphinx
  2. Local bundle with the widget ../_static/embed-periodictable.js
  3. Libraries from nbsphinx (only requirejs appears as jupyter widget was drop using #378 fix)

If jupyter-sphinx is removed, requireJS is loaded after the local widget bundle. Therefore those widgets are not loaded (error: define is undefined).

For now the best configuration I found is to use jupyter-sphinx just to ensure requireJS to be loaded before the local widget bundle. And I set nbsphinx_requirejs_path and nbsphinx_widgets_path to "" to ensure they are not loaded twice.

I know that requireJS has been moved to a later stage following #409. So I don't rely know what could be a good solution except documenting it. Or maybe you know a better hook than builder-inited to insert the local widget bundle.

mgeier commented 3 years ago

Thanks for the report!

It is indeed unfortunate that I moved require.js as far down as I could, and now you need it further up ...

Luckily, in Sphinx you can customize everything. Instead of using the Python API to inject your <script> elements, you can also modify the layout.html template like this:

{% extends "!layout.html" %}

{% block scripts %}
{{ super() }}
<script src="{{ pathto('_static/embed-periodictable.js', 1) }}"></script>
{% endblock %}

This way, your <script> tag will always come after the others.

Does that work for you?

So I don't rely know what could be a good solution except documenting it.

It would be great if you could provide a PR with improved documentation!

fcollonval commented 3 years ago

Thanks for the feedback @mgeier

I unfortunately did not have time to test the fix - but it sounds correct.

I added some pointers in the documentation. Hope it is meaningful.