Skip to content

Commit

Permalink
Close #159. Combine libembed and output scripts into single dependenc…
Browse files Browse the repository at this point in the history
…y to avoid Quarto dependency ordering bug
  • Loading branch information
cpsievert committed Sep 17, 2024
1 parent 1c97ac3 commit 5c01af7
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 30 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to shinywidgets will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [UNRELEASED]

* Fixed an issue where widgets would sometimes fail to render in a Quarto document. (#159)

## [0.3.3] - 2024-08-13

* Fixed a bug with receiving binary data on the frontend, which gets [quak](https://github.com/manzt/quak) and [mosaic-widget](https://idl.uw.edu/mosaic/jupyter/) working with `@render_widget`. (#152)
Expand Down
2 changes: 1 addition & 1 deletion shinywidgets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

__author__ = """Carson Sievert"""
__email__ = "[email protected]"
__version__ = "0.3.3"
__version__ = "0.3.3.9000"

from ._as_widget import as_widget
from ._dependencies import bokeh_dependency
Expand Down
49 changes: 22 additions & 27 deletions shinywidgets/_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,33 @@


# TODO: scripts/static_download.R should produce/update these
def libembed_dependency() -> List[HTMLDependency]:
return [
# Jupyter Notebook/Lab both come "preloaded" with several @jupyter-widgets packages
# (i.e., base, controls, output), all of which are bundled into this extension.js file
# provided by the widgetsnbextension package, which is a dependency of ipywidgets.
# https://github.com/nteract/nes/tree/master/portable-widgets
# https://github.com/jupyter-widgets/ipywidgets/blob/88cec8/packages/html-manager/src/htmlmanager.ts#L115-L120
#
# Unfortunately, I don't think there is a good way for us to "pre-bundle" these dependencies
# since they could change depending on the version of ipywidgets (and ipywidgets itself
# doesn't include these dependencies in such a way that require("@jupyter-widget/base") would
# work robustly when used in other 3rd party widgets). Moreover, I don't think we can simply
# have @jupyter-widget/base point to https://unpkg.com/@jupyter-widgets/base@__version__/lib/index.js
# (or a local version of this) since it appears the lib entry points aren't usable in the browser.
#
# All this is to say that I think we are stuck with this mega 3.5MB file that contains all of the
# stuff we need to render widgets outside of the notebook.
HTMLDependency(
name="ipywidget-libembed-amd",
version=parse_version_safely(__html_manager_version__),
source={"package": "shinywidgets", "subdir": "static"},
script={"src": "libembed-amd.js"},
),
]


def output_binding_dependency() -> HTMLDependency:
# Jupyter Notebook/Lab both come "preloaded" with several @jupyter-widgets packages
# (i.e., base, controls, output), all of which are bundled into this extension.js file
# provided by the widgetsnbextension package, which is a dependency of ipywidgets.
# https://github.com/nteract/nes/tree/master/portable-widgets
# https://github.com/jupyter-widgets/ipywidgets/blob/88cec8/packages/html-manager/src/htmlmanager.ts#L115-L120
#
# Unfortunately, I don't think there is a good way for us to "pre-bundle" these dependencies
# since they could change depending on the version of ipywidgets (and ipywidgets itself
# doesn't include these dependencies in such a way that require("@jupyter-widget/base") would
# work robustly when used in other 3rd party widgets). Moreover, I don't think we can simply
# have @jupyter-widget/base point to https://unpkg.com/@jupyter-widgets/base@__version__/lib/index.js
# (or a local version of this) since it appears the lib entry points aren't usable in the browser.
#
# All this is to say that I think we are stuck with this mega 3.5MB file that contains all of the
# stuff we need to render widgets outside of the notebook.
return HTMLDependency(
name="ipywidget-output-binding",
version=__version__,
source={"package": "shinywidgets", "subdir": "static"},
script={"src": "output.js"},
script=[
{"src": "libembed-amd.js"},
# Bundle our output.js in the same dependency as libembded since Quarto
# has a bug where it doesn't renders dependencies in the order they are defined
# (i.e., this way we can ensure the output.js script always comes after the libembed-amd.js script tag)
{"src": "output.js"},
],
stylesheet={"href": "shinywidgets.css"},
)

Expand Down
3 changes: 1 addition & 2 deletions shinywidgets/_output_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from shiny.ui.fill import as_fill_item, as_fillable_container

from ._cdn import SHINYWIDGETS_CDN, SHINYWIDGETS_CDN_ONLY
from ._dependencies import libembed_dependency, output_binding_dependency
from ._dependencies import output_binding_dependency

__all__ = ("output_widget",)

Expand All @@ -23,7 +23,6 @@ def output_widget(
) -> Tag:
id = resolve_id(id)
res = tags.div(
*libembed_dependency(),
output_binding_dependency(),
head_content(
tags.script(
Expand Down

0 comments on commit 5c01af7

Please sign in to comment.