diff --git a/datasette/app.py b/datasette/app.py index d9b61c51..fe461d42 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -2,7 +2,6 @@ import asyncio import click import collections import hashlib -import itertools import os import sys import threading @@ -258,33 +257,6 @@ class Datasette: def get_view_definition(self, database_name, view): return self.get_table_definition(database_name, view, 'view') - def asset_urls(self, key): - # Flatten list-of-lists from plugins: - seen_urls = set() - for url_or_dict in itertools.chain( - itertools.chain.from_iterable(getattr(pm.hook, key)()), - (self.metadata(key) or []) - ): - if isinstance(url_or_dict, dict): - url = url_or_dict["url"] - sri = url_or_dict.get("sri") - else: - url = url_or_dict - sri = None - if url in seen_urls: - continue - seen_urls.add(url) - if sri: - yield {"url": url, "sri": sri} - else: - yield {"url": url} - - 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 update_with_inherited_metadata(self, metadata): # Fills in source/license with defaults, if available metadata.update( diff --git a/datasette/hookspecs.py b/datasette/hookspecs.py index 95cae450..6db95344 100644 --- a/datasette/hookspecs.py +++ b/datasette/hookspecs.py @@ -16,12 +16,12 @@ def prepare_jinja2_environment(env): @hookspec -def extra_css_urls(): +def extra_css_urls(template, database, table, datasette): "Extra CSS URLs added by this plugin" @hookspec -def extra_js_urls(): +def extra_js_urls(template, database, table, datasette): "Extra JavaScript URLs added by this plugin" diff --git a/datasette/views/base.py b/datasette/views/base.py index 73036191..119b376b 100644 --- a/datasette/views/base.py +++ b/datasette/views/base.py @@ -1,5 +1,6 @@ import asyncio import csv +import itertools import json import re import time @@ -46,6 +47,32 @@ class DatasetteError(Exception): class RenderMixin(HTTPMethodView): + def _asset_urls(self, key, template, context): + # Flatten list-of-lists from plugins: + seen_urls = set() + for url_or_dict in itertools.chain( + itertools.chain.from_iterable(getattr(pm.hook, key)( + template=template.name, + database=context.get("database"), + table=context.get("table"), + datasette=self.ds + )), + (self.ds.metadata(key) or []) + ): + if isinstance(url_or_dict, dict): + url = url_or_dict["url"] + sri = url_or_dict.get("sri") + else: + url = url_or_dict + sri = None + if url in seen_urls: + continue + seen_urls.add(url) + if sri: + yield {"url": url, "sri": sri} + else: + yield {"url": url} + def render(self, templates, **context): template = self.ds.jinja_env.select_template(templates) select_templates = [ @@ -69,6 +96,12 @@ class RenderMixin(HTTPMethodView): "select_templates": select_templates, "zip": zip, "body_scripts": body_scripts, + "extra_css_urls": self._asset_urls( + "extra_css_urls", template, context + ), + "extra_js_urls": self._asset_urls( + "extra_js_urls", template, context + ), } } ) @@ -432,8 +465,6 @@ class BaseView(RenderMixin): "url_csv": url_csv, "url_csv_path": url_csv_path, "url_csv_args": url_csv_args, - "extra_css_urls": self.ds.extra_css_urls(), - "extra_js_urls": self.ds.extra_js_urls(), "datasette_version": __version__, "config": self.ds.config_dict(), } diff --git a/datasette/views/index.py b/datasette/views/index.py index 89888e4f..32c04585 100644 --- a/datasette/views/index.py +++ b/datasette/views/index.py @@ -51,6 +51,4 @@ class IndexView(RenderMixin): 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(), ) diff --git a/docs/plugins.rst b/docs/plugins.rst index 8872a4ac..deba6172 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -231,6 +231,9 @@ The full list of available plugin hooks is as follows. prepare_connection(conn) ~~~~~~~~~~~~~~~~~~~~~~~~ +``conn`` - sqlite3 connection object + The connection that is being opened + This hook is called when a new SQLite database connection is created. You can use it to `register custom SQL functions `_, aggregates and collations. For example: @@ -252,6 +255,9 @@ arguments and can be called like this:: prepare_jinja2_environment(env) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``env`` - jinja2 Environment + The template environment that is being prepared + This hook is called with the Jinja2 environment that is used to evaluate Datasette HTML templates. You can use it to do things like `register custom template filters `_, for @@ -269,10 +275,22 @@ You can now use this filter in your custom templates like so:: Table name: {{ table|uppercase }} -extra_css_urls() -~~~~~~~~~~~~~~~~ +extra_css_urls(template, database, table, datasette) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Return a list of extra CSS URLs that should be included on every page. These can +``template`` - string + The template that is being rendered, e.g. ``database.html`` + +``database`` - string or None + The name of the database + +``table`` - string or None + The name of the table + +``datasette`` - Datasette instance + You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)`` + +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`. This can be a list of URLs: @@ -301,8 +319,10 @@ Or a list of dictionaries defining both a URL and an 'sri': 'sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4', }] -extra_js_urls() -~~~~~~~~~~~~~~~ +extra_js_urls(template, database, table, datasette) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Same arguments as ``extra_css_urls``. This works in the same way as ``extra_css_urls()`` but for JavaScript. You can return either a list of URLs or a list of dictionaries: @@ -334,6 +354,9 @@ you have one: publish_subcommand(publish) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``publish`` - Click publish command group + The Click command group for the ``datasette publish`` subcommand + This hook allows you to create new providers for the ``datasette publish`` command. Datasette uses this hook internally to implement the default ``now`` and ``heroku`` subcommands, so you can read @@ -351,8 +374,8 @@ Lets you customize the display of values within table cells in the HTML table vi ``column`` - string The name of the column being rendered -``table`` - string - The name of the table +``table`` - string or None + The name of the table - or ``None`` if this is a custom SQL query ``database`` - string The name of the database @@ -411,6 +434,18 @@ If the value matches that pattern, the plugin returns an HTML link element: extra_body_script(template, database, table, datasette) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``template`` - string + The template that is being rendered, e.g. ``database.html`` + +``database`` - string or None + The name of the database, or ``None`` if the page does not correspond to a database (e.g. the root page) + +``table`` - string or None + The name of the table, or ``None`` if the page does not correct to a table + +``datasette`` - Datasette instance + You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)`` + Extra JavaScript to be added to a ``