diff --git a/datasette/app.py b/datasette/app.py
index 57f893fe..9c9b7de4 100644
--- a/datasette/app.py
+++ b/datasette/app.py
@@ -12,7 +12,6 @@ import dataclasses
import datetime
import functools
import glob
-import hashlib
import httpx
import importlib.metadata
import inspect
@@ -123,6 +122,7 @@ from .utils import (
parse_metadata,
resolve_env_secrets,
resolve_routes,
+ sha256_file,
tilde_decode,
tilde_encode,
to_css_class,
@@ -314,7 +314,7 @@ async def favicon(request, send):
send,
str(FAVICON_PATH),
content_type="image/png",
- headers={"Cache-Control": "max-age=3600, immutable, public"},
+ headers={"Cache-Control": "max-age=3600, public"},
)
@@ -348,6 +348,16 @@ def _legacy_template_csrftoken(context):
return ""
+def _resolve_static_asset_path(root_path, path):
+ root = Path(root_path).resolve()
+ full_path = (root / path).resolve()
+ try:
+ full_path.relative_to(root)
+ except ValueError:
+ raise ValueError("Static asset path cannot escape static root") from None
+ return full_path
+
+
# Documentation for the variables Datasette.render_template() adds to the
# context for every page. This is part of the documented template contract:
# keys added in render_template() must be documented here - the contract
@@ -361,9 +371,6 @@ TEMPLATE_BASE_CONTEXT = {
"menu_links": "Async function returning links for the Datasette application menu, including links added by plugins. Each item is a link dictionary with ``href`` and ``label`` keys. See :ref:`plugin_hook_menu_links`; for page action menus that can also include JavaScript-backed buttons, see :ref:`plugin_actions`.",
"display_actor": "Function that accepts an actor dictionary and returns the display string used in the navigation menu.",
"show_logout": "True if the logout link should be shown in the navigation menu",
- "app_css_hash": "Hash of Datasette's app.css contents, used for cache busting",
- "edit_tools_js_hash": "Hash of Datasette's edit-tools.js contents, used for cache busting",
- "table_js_hash": "Hash of Datasette's table.js contents, used for cache busting",
"zip": "Python's ``zip()`` builtin, made available to template logic",
"body_scripts": 'List of JavaScript snippets contributed by plugins using :ref:`plugin_hook_extra_body_script`. Each item is a dictionary with ``script`` containing JavaScript source and ``module`` indicating whether Datasette will wrap it in ``
-
+
+
diff --git a/datasette/templates/row.html b/datasette/templates/row.html
index 5e483d34..aa1f0ecd 100644
--- a/datasette/templates/row.html
+++ b/datasette/templates/row.html
@@ -7,9 +7,9 @@
{% if row_mutation_ui %}
{% if table_page_data.foreignKeys %}
-
+
{% endif %}
-
+
{% endif %}