diff --git a/@plotly/dash-generator-test-component-standard/base/__init__.py b/@plotly/dash-generator-test-component-standard/base/__init__.py index c72087cde2..fb1bae5541 100644 --- a/@plotly/dash-generator-test-component-standard/base/__init__.py +++ b/@plotly/dash-generator-test-component-standard/base/__init__.py @@ -16,8 +16,21 @@ dict( relative_package_path='dash_generator_test_component_standard.js', namespace='dash_generator_test_component_standard' + ), + dict( + relative_package_path='godfather.ttf', + namespace='dash_generator_test_component_standard', + dynamic=True + ) +] + +_css_dist = [ + dict( + relative_package_path='style.css', + namespace='dash_generator_test_component_standard' ) ] for _component in __all__: setattr(locals()[_component], '_js_dist', _js_dist) + setattr(locals()[_component], '_css_dist', _css_dist) diff --git a/@plotly/dash-generator-test-component-standard/base/godfather.ttf b/@plotly/dash-generator-test-component-standard/base/godfather.ttf new file mode 100644 index 0000000000..a97301daa0 Binary files /dev/null and b/@plotly/dash-generator-test-component-standard/base/godfather.ttf differ diff --git a/@plotly/dash-generator-test-component-standard/base/style.css b/@plotly/dash-generator-test-component-standard/base/style.css new file mode 100644 index 0000000000..f69de0e7ec --- /dev/null +++ b/@plotly/dash-generator-test-component-standard/base/style.css @@ -0,0 +1,4 @@ +@font-face { + font-family: 'godfather'; + src: url(./godfather.ttf) format('truetype'); +} \ No newline at end of file diff --git a/@plotly/dash-generator-test-component-standard/src/components/MyStandardComponent.js b/@plotly/dash-generator-test-component-standard/src/components/MyStandardComponent.js index df9ab777b8..b9597fba71 100644 --- a/@plotly/dash-generator-test-component-standard/src/components/MyStandardComponent.js +++ b/@plotly/dash-generator-test-component-standard/src/components/MyStandardComponent.js @@ -4,7 +4,7 @@ import React from 'react'; /** * MyComponent description */ -const MyStandardComponent = ({ id, value }) => (
{value}
); +const MyStandardComponent = ({ id, style, value }) => (
{value}
); MyStandardComponent.propTypes = { /** @@ -12,6 +12,11 @@ MyStandardComponent.propTypes = { */ id: PropTypes.string, + /** + * The style + */ + style: PropTypes.shape, + /** * The value to display */ diff --git a/CHANGELOG.md b/CHANGELOG.md index 86e4be2efa..b7a012bff1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [UNRELEASED] ### Added - [#1201](https://github.com/plotly/dash/pull/1201) New attribute `app.validation_layout` allows you to create a multi-page app without `suppress_callback_exceptions=True` or layout function tricks. Set this to a component layout containing the superset of all IDs on all pages in your app. +- [#1078](https://github.com/plotly/dash/pull/1078) Permit usage of arbitrary file extensions for assets within component libraries ### Fixed - [#1201](https://github.com/plotly/dash/pull/1201) Fixes [#1193](https://github.com/plotly/dash/issues/1193) - prior to Dash 1.11, you could use `flask.has_request_context() == False` inside an `app.layout` function to provide a special layout containing all IDs for validation purposes in a multi-page app. Dash 1.11 broke this when we moved most of this validation into the renderer. This change makes it work again. @@ -72,7 +73,7 @@ These functions are particularly useful for apps deployed on Dash Enterprise whe ### Changed - [#1035](https://github.com/plotly/dash/pull/1035) Simplify our build process. -- [#1074](https://github.com/plotly/dash/pull/1045) Error messages when providing an incorrect property to a component have been improved: they now specify the component type, library, version, and ID (if available). +- [#1074](https://github.com/plotly/dash/pull/1074) Error messages when providing an incorrect property to a component have been improved: they now specify the component type, library, version, and ID (if available). ### Fixed - [#1037](https://github.com/plotly/dash/pull/1037) Fix no_update test to allow copies, such as those stored and retrieved from a cache. diff --git a/dash/dash.py b/dash/dash.py index a31fbc22c2..dd9f505973 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -11,6 +11,7 @@ import threading import re import logging +import mimetypes from functools import wraps @@ -45,6 +46,9 @@ from . import _validate from . import _watch +# Add explicit mapping for map files +mimetypes.add_type("application/json", ".map", True) + _default_index = """ @@ -669,13 +673,8 @@ def serve_component_suites(self, package_name, fingerprinted_path): _validate.validate_js_path(self.registered_paths, package_name, path_in_pkg) - mimetype = ( - { - "js": "application/javascript", - "css": "text/css", - "map": "application/json", - } - )[path_in_pkg.split(".")[-1]] + extension = "." + path_in_pkg.split(".")[-1] + mimetype = mimetypes.types_map.get(extension, "application/octet-stream") package = sys.modules[package_name] self.logger.debug( diff --git a/dash/development/_r_components_generation.py b/dash/development/_r_components_generation.py index 7ed2d52f88..577cc914e3 100644 --- a/dash/development/_r_components_generation.py +++ b/dash/development/_r_components_generation.py @@ -505,7 +505,7 @@ def write_js_metadata(pkg_data, project_shortname, has_wildcards): for filename in filenames: extension = os.path.splitext(filename)[1] - if extension not in [".css", ".js", ".map"]: + if extension in [".py", ".pyc", ".json"]: continue target_dirname = os.path.join( diff --git a/tests/integration/test_generation.py b/tests/integration/test_generation.py index fe1fbf7ad1..518c7a0af7 100644 --- a/tests/integration/test_generation.py +++ b/tests/integration/test_generation.py @@ -1,7 +1,12 @@ from dash import Dash +from dash.dependencies import Input, Output +from dash.exceptions import PreventUpdate + from dash_generator_test_component_nested import MyNestedComponent from dash_generator_test_component_standard import MyStandardComponent -from dash_html_components import Div +from dash_html_components import Button, Div + +from selenium.webdriver.support.ui import WebDriverWait def test_gene001_simple_callback(dash_duo): @@ -18,3 +23,39 @@ def test_gene001_simple_callback(dash_duo): assert dash_duo.wait_for_element("#standard").text == "Standard" assert dash_duo.wait_for_element("#nested").text == "Nested" + + dash_duo.percy_snapshot(name="gene001-simple-callback") + + +def test_gene002_arbitrary_resources(dash_duo): + app = Dash(__name__) + + app.layout = Div([Button(id="btn"), Div(id="container")]) + + @app.callback(Output("container", "children"), [Input("btn", "n_clicks")]) + def update_container(n_clicks): + if n_clicks is None: + raise PreventUpdate + + return MyStandardComponent( + id="standard", value="Standard", style={"font-family": "godfather"} + ) + + dash_duo.start_server(app) + + assert ( + dash_duo.driver.execute_script("return document.fonts.check('1em godfather')") + is False + ) + + dash_duo.wait_for_element("#btn").click() + assert dash_duo.wait_for_element("#standard").text == "Standard" + + WebDriverWait(dash_duo.driver, 10).until( + lambda _: dash_duo.driver.execute_script( + "return document.fonts.check('1em godfather')" + ) + is True, + ) + + dash_duo.percy_snapshot(name="gene002-arbitrary-resource")