From 0120c24927af364304574ab1a58e417094e01c22 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 28 Nov 2017 18:38:15 -0800 Subject: [PATCH] extra_css_urls/extra_js_urls in metadata, refs #153 A mechanism in the metadata.json format for adding custom CSS and JS urls. Create a metadata.json file that looks like this: { "extra_css_urls": [ "https://simonwillison.net/static/css/all.bf8cd891642c.css" ], "extra_js_urls": [ "https://code.jquery.com/jquery-3.2.1.slim.min.js" ] } Then start datasette like this: datasette mydb.db --metadata=metadata.json The CSS and JavaScript files will be linked in the of every page. You can also specify a SRI (subresource integrity hash) for these assets: { "extra_css_urls": [ { "url": "https://simonwillison.net/static/css/all.bf8cd891642c.css", "sri": "sha384-9qIZekWUyjCyDIf2YK1FRoKiPJq4PHt6tp/ulnuuyRBvazd0hG7pWbE99zvwSznI" } ], "extra_js_urls": [ { "url": "https://code.jquery.com/jquery-3.2.1.slim.min.js", "sri": "sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g=" } ] } Modern browsers will only execute the stylsheet or JavaScript if the SRI hash matches the content served. You can generate hashes using www.srihash.org --- datasette/app.py | 22 ++++++++++++++++++++++ datasette/templates/base.html | 6 ++++++ 2 files changed, 28 insertions(+) diff --git a/datasette/app.py b/datasette/app.py index 3adedd17..82f2ddf2 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -232,6 +232,8 @@ class BaseView(HTTPMethodView): 'url_json': path_with_ext(request, '.json'), 'url_jsono': path_with_ext(request, '.jsono'), 'metadata': self.ds.metadata, + 'extra_css_urls': self.ds.extra_css_urls(), + 'extra_js_urls': self.ds.extra_js_urls(), 'datasette_version': __version__, } } @@ -296,6 +298,8 @@ class IndexView(HTTPMethodView): databases=databases, metadata=self.ds.metadata, datasette_version=__version__, + extra_css_urls=self.ds.extra_css_urls(), + extra_js_urls=self.ds.extra_js_urls(), ) @@ -773,6 +777,24 @@ class Datasette: self.sqlite_functions = [] self.sqlite_extensions = sqlite_extensions or [] + def asset_urls(self, key): + for url_or_dict in (self.metadata.get(key) or []): + if isinstance(url_or_dict, dict): + yield { + 'url': url_or_dict['url'], + 'sri': url_or_dict.get('sri'), + } + else: + yield { + 'url': url_or_dict, + } + + def extra_css_urls(self): + return self.asset_urls('extra_css_urls') + + def extra_js_urls(self): + return self.asset_urls('extra_js_urls') + def prepare_connection(self, conn): conn.row_factory = sqlite3.Row conn.text_factory = lambda x: str(x, 'utf-8', 'replace') diff --git a/datasette/templates/base.html b/datasette/templates/base.html index 1976b4ac..7db54460 100644 --- a/datasette/templates/base.html +++ b/datasette/templates/base.html @@ -4,6 +4,12 @@ {% block title %}{% endblock %} +{% for url in extra_css_urls %} + +{% endfor %} +{% for url in extra_js_urls %} + +{% endfor %} {% block extra_head %}{% endblock %}