danielfrg / mkdocs-jupyter

Use Jupyter Notebook in mkdocs
https://mkdocs-jupyter.danielfrg.com
Apache License 2.0
385 stars 47 forks source link

Plotly plots not showing #107

Closed tvdboom closed 1 year ago

tvdboom commented 1 year ago

Is there a way to make plotly plots show? Right now they appear blank.

tvdboom commented 1 year ago

I solved the issue myself. Apparently the plotly plots don't render properly because the html page contains a part that isn't necessary. Removing that part solves the issue.

Using the mkdocs-simple-hooks library you can create a plugin that changes the necessary html like this:

def convert_plotly(html: str, **kwargs) -> str:
    # Remove plotly js (remove this to not pollute the search index and use <script src="https://cdn.plot.ly/plotly-2.14.0.min.js"></script> instead)
    html = re.sub('<div class="jp-RenderedHTMLCommon jp-RenderedHTML jp-OutputArea-output " data-mime-type="text\/html">\s*?<script type="text\/javascript">.*?<\/script>\s*?<\/div>', "", html, flags=re.S)

    # Fix plots in jupyter notebook
    html = re.sub('(?<=<script type="text\/javascript">)\s*?require\(\["plotly"\], function\(Plotly\) {\s*?(?=window\.PLOTLYENV)', "", html)
    html = re.sub('\).then\(function\(\){.*?(?=<\/script>)', ')}', html, flags=re.S)

    return html

To keep the search index small (if it's too large it doesn't work properly), remove the plotly graphs and mkdocs-jupyter css like this:

def clean_search(config):
    with open(f"{config.data['site_dir']}/search/search_index.json", "r") as f:
        search = json.load(f)

    for elem in search["docs"]:
        # Remove plotly graphs
        elem["text"] = re.sub("window\.PLOTLYENV.*?\)\s*?}\s*?", "", elem["text"], flags=re.S)

        # Remove mkdocs-jupyter css
        elem["text"] = re.sub("\(function \(global, factory.*?(?=Example:)", "", elem["text"], flags=re.S)

    with open(f"{config.data['site_dir']}/search/search_index.json", "w") as f:
        json.dump(search, f)

and add this to the mkdocs.yml file:

plugins:
    - search
    - autorefs
    - mkdocs-simple-hooks:
        hooks:
            on_page_content: "docs_sources.XXX:convert_plotly"
            on_post_build: "docs_sources.XXX:clean_search"

Hope this helps other people with the same issue.

core-engineering commented 1 year ago

Hi @tvdboom,

I have tried to follow your solution but unfortunetly, it doesn't work on my side. Have you any update on your code ?

Regards,

tvdboom commented 1 year ago

I don't. That did it for me. You can see it implemented in this repo

core-engineering commented 1 year ago

@tvdboom, even with your nice repo, I didn't succeed to use your trick.

My poor workaround : fig.show(renderer="png") works out of the box !

hwjohn commented 1 year ago

I love mkdocs-jupyter, but this issue has become a blocking point for me. Unfortunately, I can't get the above workaround to work. Has anyone else encountered this issue?

qchenevier commented 1 year ago

The workaround doesn't work as using regexes to modify html is a bit hacky and is expected to break as soon as the structure of the html changes a bit. 😬

However, enabling requireJS as shown in the README solves the issue (for me at least). You only need to add this to your mkdocs.yml file:

plugins:
  - mkdocs-jupyter:
      include_requirejs: true
hwjohn commented 1 year ago

@qchenevier , that fixed it! Thanks much! 🍻

@tvdboom , I think you can close this issue.

samuelefiorini commented 8 months ago

In my case include_requirejs: true was not enough. I also added

import plotly.express as px
import plotly.io as pio

# This ensures Plotly output works in multiple places:
pio.renderers.default = "plotly_mimetype+notebook"

fig = px.line(...)
fig.show()

as shown here.