randyzwitch / streamlit-folium

Streamlit Component for rendering Folium maps
https://folium.streamlit.app/
MIT License
468 stars 176 forks source link

Generate javascript and css links based on the generated Folium map #180

Closed hansthen closed 5 months ago

hansthen commented 5 months ago

The coming release of Folium (0.17) will allow users to add (and override) javascript and css files at runtime. This would break the currently hardcoded list of javascript and css links in public/index.html.

The Folium generated code contains links to include the required javascript and css files. Is there some way these could be included in the generated code? Also, are there things we could change in the Folium API to make this easier for you?

randyzwitch commented 5 months ago

Also, are there things we could change in the Folium API to make this easier for you?

@blackary is the better person to answer this, but I wonder if part of the folium JSON spec, you could have a list of the required dependencies? I think a lot of our issues are trying to strike a balance of not having to scrape the JSON to infer things/performance and secondarily streamlit might not be able to dynamically insert JS?

hansthen commented 5 months ago

In Folium the things that generate links (js or css) are instances of JSCSSMixin. I just did a small experiment with the following code:

def walk(fig):
    if isinstance(fig, folium.elements.JSCSSMixin):
        yield fig
        for child in fig._children:
            yield from walk(child)

for elem in walk(map):
    print(elem.default_css)
    print(elem.default_js)

This prints something like this:

[('leaflet_css', 'https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.css'), ('bootstrap_css', 'https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css'), ('glyphicons_css', 'https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css'), ('awesome_markers_font_css', 'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.2.0/css/all.min.css'), ('awesome_markers_css', 'https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css'), ('awesome_rotate_css', 'https://cdn.jsdelivr.net/gh/python-visualization/folium/folium/templates/leaflet.awesome.rotate.min.css')]
[('leaflet', 'https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.js'), ('jquery', 'https://code.jquery.com/jquery-3.7.1.min.js'), ('bootstrap', 'https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js'), ('awesome_markers', 'https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js')]

These links could somehow be added to the component, but I don't know yet how. I can study the __init__.py to see if I can find a way, but pointers would be helpful.

blackary commented 5 months ago

That's pretty slick!

The two most difficult parts, I think will be:

  1. Figuring out how to dynamically update index.html to include the correct modules
  2. Making sure the imports are in the right order (I've faced issues before where if I arrange the js imports in the wrong order, the page breaks because of some dependency that hasn't been declared yet).
hansthen commented 5 months ago

I took a stab at a pull request to generate the links dynamically. https://github.com/randyzwitch/streamlit-folium/pull/181

I performed manual tests against the example app.

Unfortunately I also broke the automated tests. I have little experience with playwrite and I do not see immediately what is wrong there. All the Locator.click() calls seem to timeout.

Could someone help me check why the automated tests are all broken in this version?