Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plotly plots rendered by nbsphinx not showing in sphinx_rtd_theme #788

Closed
astrojuanlu opened this issue Jul 20, 2019 · 17 comments
Closed

Plotly plots rendered by nbsphinx not showing in sphinx_rtd_theme #788

astrojuanlu opened this issue Jul 20, 2019 · 17 comments
Labels
Status: blocked Issue is blocked on another issue

Comments

@astrojuanlu
Copy link
Contributor

astrojuanlu commented Jul 20, 2019

Hi... sorry I'm the Plotly guy again 🙏 You may remember me from such issues as readthedocs/readthedocs.org#4367 #328 and others.

Problem

Plotly plots rendered by nbsphinx show (both locally and remotely) when using Alabaster just fine, but they don't show at all when using sphinx_rtd_theme.

Reproducible Project

Error Logs/Results

Interestingly, the web developer console shows nothing with Alabaster, but with rtd_sphinx_theme shows a bunch of errors:

Screenshot from 2019-07-20 19-43-53

Expected Results

Plots should show regardless of the theme.

Environment Info

  • Python Version: 3.7.4
  • Sphinx Version: 2.1.2
  • RTD Theme Version: 0.4.3
@astrojuanlu
Copy link
Contributor Author

Commenting out this line brings Plotly back to life:

<script type="text/javascript" src="{{ pathto('_static/js/theme.js', 1) }}"></script>

And, looking at theme.js, it seems that require is already defined there:

require=function r(s,a,l){function c(e,n){if(!a[e]){if(!s[e]){var i="function"==typeof require&&require;if(!n&&i)return i(e,!0);if(u)return u(e,!0);var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}var o=a[e]={exports:{}};s[e][0].call(o.exports,function(n){return c(s[e][1][n]||n)},o,o.exports,r,s,a,l)}return a[e].exports}for(var u="function"==typeof require&&require,n=0;n<l.length;n++)c(l[n]);return c}({"sphinx-rtd-theme":[function(n,e,i){var jQuery="undefined"!=typeof window?window.jQuery:n("jquery");e.exports.ThemeNav={navBar:null,win:null,winScroll:!1,winResize:!1,linkScroll:!1,winPosition:0,winHeight:null,docHeight:null,isRunning:!1,enable:function(e){var i=this;void 0===e&&(e=!0),i.isRunning||(i.isRunning=!0,jQuery(function(n){i.init(n),i.reset(),i.win.on("hashchange",i.reset),e&&i.win.on("scroll",function(){i.linkScroll||i.winScroll||(i.winScroll=!0,requestAnimationFrame(function(){i.onScroll()}))}),i.win.on("resize",function(){i.winResize||(i.winResize=!0,requestAnimationFrame(function(){i.onResize()}))}),i.onResize()}))},enableSticky:function(){this.enable(!0)},init:function(i){i(document);var t=this;this.navBar=i("div.wy-side-scroll:first"),this.win=i(window),i(document).on("click","[data-toggle='wy-nav-top']",function(){i("[data-toggle='wy-nav-shift']").toggleClass("shift"),i("[data-toggle='rst-versions']").toggleClass("shift")}).on("click",".wy-menu-vertical .current ul li a",function(){var n=i(this);i("[data-toggle='wy-nav-shift']").removeClass("shift"),i("[data-toggle='rst-versions']").toggleClass("shift"),t.toggleCurrent(n),t.hashChange()}).on("click","[data-toggle='rst-current-version']",function(){i("[data-toggle='rst-versions']").toggleClass("shift-up")}),i("table.docutils:not(.field-list,.footnote,.citation)").wrap("<div class='wy-table-responsive'></div>"),i("table.docutils.footnote").wrap("<div class='wy-table-responsive footnote'></div>"),i("table.docutils.citation").wrap("<div class='wy-table-responsive citation'></div>"),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var e=i(this);expand=i('<span class="toctree-expand"></span>'),expand.on("click",function(n){return t.toggleCurrent(e),n.stopPropagation(),!1}),e.prepend(expand)})},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),i=e.find('[href="'+n+'"]');if(0===i.length){var t=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(i=e.find('[href="#'+t.attr("id")+'"]')).length&&(i=e.find('[href="#"]'))}0<i.length&&($(".wy-menu-vertical .current").removeClass("current"),i.addClass("current"),i.closest("li.toctree-l1").addClass("current"),i.closest("li.toctree-l1").parent().addClass("current"),i.closest("li.toctree-l1").addClass("current"),i.closest("li.toctree-l2").addClass("current"),i.closest("li.toctree-l3").addClass("current"),i.closest("li.toctree-l4").addClass("current"),i[0].scrollIntoView())}catch(o){console.log("Error expanding nav for anchor",o)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,i=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(i),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current"),e.siblings().find("li.current").removeClass("current"),e.find("> ul li.current").removeClass("current"),e.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:e.exports.ThemeNav,StickyNav:e.exports.ThemeNav}),function(){for(var r=0,n=["ms","moz","webkit","o"],e=0;e<n.length&&!window.requestAnimationFrame;++e)window.requestAnimationFrame=window[n[e]+"RequestAnimationFrame"],window.cancelAnimationFrame=window[n[e]+"CancelAnimationFrame"]||window[n[e]+"CancelRequestAnimationFrame"];window.requestAnimationFrame||(window.requestAnimationFrame=function(n,e){var i=(new Date).getTime(),t=Math.max(0,16-(i-r)),o=window.setTimeout(function(){n(i+t)},t);return r=i+t,o}),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(n){clearTimeout(n)})}()},{jquery:"jquery"}]},{},["sphinx-rtd-theme"]);

Notice that Plotly needs require.js, but the require defined in the sphinx_rtd_theme seems to be not compatible with it. If I comment out the require.js import:

Screenshot from 2019-07-21 01-40-02

Therefore I tried something crazy:

$ sed -i 's/require/require_rtd/g' _static/js/theme.js

And now everything works like a charm.

astrojuanlu added a commit to astrojuanlu/sphinx_rtd_theme that referenced this issue Jul 20, 2019
astrojuanlu added a commit to astrojuanlu/poliastro that referenced this issue Jul 21, 2019
astrojuanlu added a commit to astrojuanlu/poliastro that referenced this issue Jul 21, 2019
@humitos
Copy link
Member

humitos commented Jul 21, 2019

Using Google Chrome, one thing that I found is that plotly.js is giving 404 and that's why it does not render properly on readthedocs theme. But, if you look closer, alabaster version loads https://cdn.plot.ly/plotly-latest.min.js, but readthedocs theme tries to load https://rtd-js-test.readthedocs.io/en/latest/plotly.js

Both themes load the same version of require.js from https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js so I don't think this is the problem.

I'm not sure, but I think what it's overlapping here is require module from Browserify from the Read the Docs Sphinx Theme --used here for example-- with require variable defined by require.js.

And... it seems to be a known issue: https://stackoverflow.com/a/25586213. They say that the solution could be to use window.require instead of require in the Javascript code from Read the Docs Theme.

There are more context about this on a issue on Browserify repo: browserify/browserify#790

It seems this is a potential good reason about why this is failing on Read the Docs Sphinx (BTW, alabaster does not include any JS at all).

@jessetan
Copy link
Contributor

This is a good issue to revisit after #771 is merged which moves our build process to webpack, without browserify

@agjohnson agjohnson added the Status: blocked Issue is blocked on another issue label Jul 25, 2019
@nvaytet
Copy link

nvaytet commented Oct 11, 2019

Hi, we are also trying to use plotly on our documentation pages (https://scipp.readthedocs.io/en/latest/user-guide/plotting.html#Plotting-data-with-3-and-more-dimensions).
I see that #771 was merged in July. Does this mean that in principle plotly should now just work if the Pypi package gets updated? Or does it mean that more work is required to get this working?
Thanks!

@astrojuanlu
Copy link
Contributor Author

If anything, probably this issue is not blocked anymore?

@lpravda
Copy link

lpravda commented Jan 28, 2020

Hi all, is there any update on this? pypi has not been updated since last year, and if I clone the master branch and use this, it still exhibits the same issue.

Thank you :)!

@ociule
Copy link

ociule commented Feb 13, 2020

Hi, it's a pity this hasn't been fixed yet.

What works for me is a variant of plotly/plotly.py#1033 (comment)

<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script>
<script>require=requirejs;</script>

I add this in my notebooks through a raw html include file directive.

This is easier to do by adding this to your sphinx conf.py:

nbsphinx_prolog = r"""
.. raw:: html

    <script src='http://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js'></script>
    <script>require=requirejs;</script>


"""

Note that if your notebooks use plotly.graph_objects.FigureWidget instead of Figure, this bug is not an issue.

@jaladh-singhal
Copy link

Is there any progress on this issue?

@jaladh-singhal
Copy link

Thank you so much @ociule, after quite a lot of struggle, your workaround works like charm!

<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script> <script>require=requirejs;</script>

I add this in my notebooks through a raw html include file directive.

For others who might be confused about how to insert this in a specific notebook (like I was), use Raw NBConvert cell - it doesn't get displayed & code inside it gets executed, when converted to HTML.

@jorgepiloto
Copy link

Hi all! Its Jorge, from the poliastro dev team (working with @astrojuanlu).

I saved a plotly figure in html format. Then, it is supposed this should be displayed if using:

.. raw:: html
    :file: path/to/file.html

However, once documentation is built, it only shows a white space were the figure should be displayed. I found that the following error was raised when inspecting that web element:

ReferenceError: Plotly is not defined

I am not an expert on Javascript or web development. After a little search on the web, found the following exaplantion, see here:

That can only mean that the event handler is executed before plotly is fully loaded.

If adding <script src="https://cdn.plot.ly/plotly-latest.min.js"></script> at the top of the index.html file the figure was finally properly rendered.

Maybe people with more experience on Javascript could have a better understanding about what is going on with this. Just posted this so it might be helpful 😅

@astrojuanlu
Copy link
Contributor Author

Notice that my original issue uses nbsphinx (which I failed to mention in the description of this issue, I will change that accordingly) so @jorgepiloto case might be slightly different.

@astrojuanlu astrojuanlu changed the title Plotly plots not showing in sphinx_rtd_theme Plotly plots rendered by nbsphinx not showing in sphinx_rtd_theme Apr 4, 2020
@astrojuanlu
Copy link
Contributor Author

I just tested sphinx_rtd_theme==0.5.0rc1 and the issue is fixed, along other minor annoyances! Thanks a lot for the RTD team for maintaining the best Sphinx theme out there ❤️

@jorgepiloto
Copy link

🎉

@sandipde
Copy link

This indeed solved the issue of showing the plotly figures and everthing works ! However, it's quite weired that it still complains about missing plotly.js .

domfournier added a commit to MiraGeoscience/geoapps that referenced this issue Sep 17, 2020
Attempt to fix plotly again as proposed in readthedocs/sphinx_rtd_theme#788 (comment)
@layne-sadler
Copy link

layne-sadler commented Feb 3, 2021

Attempts

  • Tried solutions above: raw cell <script>, nbsphinx_prolog = r""", and sed - but none of them worked.
  • Tried downgrading to jupyterlab==2.1, but same errors
  • Tried sphinx_rtd_theme==0.5.0rc1
  • Tried manually setting nbsphinx_requirejs_path.
  • Tried manually setting nbsphinx_requirejs_options + including plotly.js file (succeeds locally fails on RTD due to MIME type)

Errors

firefox: require.min.js error which you can get past by installing 0.5.0rc1, or setting nbsphinx_requirejs_options

Uncaught Error: Script error for "plotly"
http://requirejs.org/docs/errors.html#scripterror
    makeError https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js:1
    onScriptError https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js:1

Dependencies

docs/requirements.txt

ipython==7.19.0
nbsphinx==0.8.0
sphinx_copybutton==0.3.1
sphinx_rtd_theme==0.5.0rc1
sphinxext-opengraph==0.4.1

plotly 4.14.3


>>> jupyter labextension list

JupyterLab v3.0.6
/Users/layne/.pyenv/versions/3.8.7/envs/jupyterlab3/share/jupyter/labextensions
        @jupyter-widgets/jupyterlab-manager v3.0.0 enabled OK (python, jupyterlab_widgets)

Other labextensions (built into JupyterLab)
   app dir: /Users/layne/.pyenv/versions/3.8.7/envs/jupyterlab3/share/jupyter/lab
        jupyterlab-plotly v4.14.3 enabled OK

@layne-sadler
Copy link

layne-sadler commented Feb 3, 2021

Solved (locally)

Okay so this in conf.py gets me past the initial require.min.js error. I used the src attribute instead of nbsphinx_requirejs_path

nbsphinx_requirejs_options = {
	"src": "https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js",
	"integrity": "sha512-VCK7oF67GXNc+J7zsu5o57jtxhLA75nSMHGaq8Q8TCOxDj4nMDw5dhQZvm9Cd9RN+3zgcodqbKcRc9gyPP8a2w==",
	"crossorigin": "anonymous"
}

But then I get a new error that feels more specific to plotly.

VM58 require.min.js:34 GET file:///Users/layne/Desktop/aiqc/docs/_build/html/notebooks/plotly.js net::ERR_FILE_NOT_FOUND
h.load @ VM58 require.min.js:34
load @ VM58 require.min.js:29
load @ VM58 require.min.js:18
fetch @ VM58 require.min.js:17
check @ VM58 require.min.js:19
enable @ VM58 require.min.js:23
enable @ VM58 require.min.js:27
(anonymous) @ VM58 require.min.js:23
(anonymous) @ VM58 require.min.js:8
v @ VM58 require.min.js:7
enable @ VM58 require.min.js:22
init @ VM58 require.min.js:17
(anonymous) @ VM58 require.min.js:26
setTimeout (async)
h.nextTick @ VM58 require.min.js:32
g @ VM58 require.min.js:26
requirejs @ VM58 require.min.js:31
(anonymous) @ visualization.html:1001
VM58 require.min.js:8 Uncaught Error: Script error for: plotly
http://requirejs.org/docs/errors.html#scripterror
    at C (VM58 require.min.js:8)
    at HTMLScriptElement.onScriptError (VM58 require.min.js:29)

So copy the contents of https://cdn.plot.ly/plotly-latest.min.js (4.2 MB on disk) and save it as plotly.js in that docs/_build/html/notebooks folder then make html then clear cache and it works locally.

image

Bah but then this gets blocked on RTD

The resource from “https://aiqc.readthedocs.io/en/latest/notebooks/plotly.js” was blocked due to MIME type (“text/html”) mismatch (X-Content-Type-Options: nosniff)

@miohtama
Copy link

miohtama commented Jun 17, 2022

Although this is a closed issue, it still popups, as require.js is somewhat difficult to work with. We had this is issue for both sphinx_rtd_theme and furo theme in 2022. Here is our solution:

  • Make sure your theme loads JavaScript in <head>, not at the end of <body>
  • Server require.js locally from Sphinx _static folder
  • Configure require by using custom.js

Example conf.py:

html_js_files = [
    "require.min.js",  # Add to your _static
    "custom.js",
]

Example custom.js:

requirejs.config({
    paths: {
        base: '/static/base',
        plotly: 'https://cdn.plot.ly/plotly-2.12.1.min.js?noext',
    },
});

This way

  • Notebook correctly renders interactive diagrams when running in Jupyter
  • Notebook correctly renders interactive diagrams when viewed as static HTML files
  • Notebook correctly renders interactive diagrams when viewed on ReadTheDocs

See the example open-source documentation here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: blocked Issue is blocked on another issue
Projects
None yet
Development

No branches or pull requests