diff --git a/datasette/app.py b/datasette/app.py
index f8549fac..cfce8e0b 100644
--- a/datasette/app.py
+++ b/datasette/app.py
@@ -781,7 +781,13 @@ class Datasette:
datasette=self,
):
extra_script = await await_me_maybe(extra_script)
- body_scripts.append(Markup(extra_script))
+ if isinstance(extra_script, dict):
+ script = extra_script["script"]
+ module = bool(extra_script.get("module"))
+ else:
+ script = extra_script
+ module = False
+ body_scripts.append({"script": Markup(script), "module": module})
extra_template_vars = {}
# pylint: disable=no-member
diff --git a/datasette/templates/base.html b/datasette/templates/base.html
index 3f3d4507..e61edc4f 100644
--- a/datasette/templates/base.html
+++ b/datasette/templates/base.html
@@ -62,7 +62,7 @@
{% include "_close_open_menus.html" %}
{% for body_script in body_scripts %}
-
+
{% endfor %}
{% if select_templates %}{% endif %}
diff --git a/docs/plugin_hooks.rst b/docs/plugin_hooks.rst
index d465307b..0206daaa 100644
--- a/docs/plugin_hooks.rst
+++ b/docs/plugin_hooks.rst
@@ -168,7 +168,7 @@ Examples: `datasette-search-all
extra_css_urls(template, database, table, columns, view_name, request, datasette)
---------------------------------------------------------------------------------
-Same arguments as :ref:`extra_template_vars(...) `
+This takes the same arguments as :ref:`extra_template_vars(...) `
Return a list of extra CSS URLs that should be included on the page. These can
take advantage of the CSS class hooks described in :ref:`customization`.
@@ -217,7 +217,7 @@ Examples: `datasette-cluster-map `
+This takes the same arguments as :ref:`extra_template_vars(...) `
This works in the same way as ``extra_css_urls()`` but for JavaScript. You can
return a list of URLs, a list of dictionaries or an awaitable function that returns those things:
@@ -264,15 +264,30 @@ extra_body_script(template, database, table, columns, view_name, request, datase
Extra JavaScript to be added to a ```` element:
+
+.. code-block:: python
+
+ @hookimpl
+ def extra_body_script():
+ return {
+ "module": True,
+ "script": "console.log('Your JavaScript goes here...')"
+ }
+
+This will add the following to the end of your page:
+
+.. code-block:: html
+
+
Example: `datasette-cluster-map `_
diff --git a/tests/plugins/my_plugin.py b/tests/plugins/my_plugin.py
index 1c86b4bc..8d192d28 100644
--- a/tests/plugins/my_plugin.py
+++ b/tests/plugins/my_plugin.py
@@ -70,7 +70,7 @@ def extra_body_script(
template, database, table, view_name, columns, request, datasette
):
async def inner():
- return "var extra_body_script = {};".format(
+ script = "var extra_body_script = {};".format(
json.dumps(
{
"template": template,
@@ -90,6 +90,7 @@ def extra_body_script(
}
)
)
+ return {"script": script, "module": True}
return inner
diff --git a/tests/test_plugins.py b/tests/test_plugins.py
index 648e7abd..715c7c17 100644
--- a/tests/test_plugins.py
+++ b/tests/test_plugins.py
@@ -288,7 +288,7 @@ def test_plugin_config_file(app_client):
],
)
def test_hook_extra_body_script(app_client, path, expected_extra_body_script):
- r = re.compile(r"")
+ r = re.compile(r"")
json_data = r.search(app_client.get(path).text).group(1)
actual_data = json.loads(json_data)
assert expected_extra_body_script == actual_data