kopia lustrzana https://github.com/simonw/datasette
extra_css_urls(template, database, table, datasette)
The extra_css_urls and extra_js_urls hooks now take additional optional parameters. Also refactored them out of the Datasette class and into RenderMixin. Plus improved plugin documentation to explicitly list parameters.pull/363/head
rodzic
fbf446965b
commit
b7c6a9f9bd
|
@ -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(
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
)
|
||||
|
|
|
@ -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 <https://docs.python.org/2/library/sqlite3.html#sqlite3.Connection.create_function>`_,
|
||||
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 <http://jinja.pocoo.org/docs/2.10/api/#custom-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 ``<script>`` block at the end of the ``<body>`` element on the page.
|
||||
|
||||
The ``template``, ``database`` and ``table`` options can be used to return different code depending on which template is being rendered and which database or table are being processed.
|
||||
|
|
|
@ -204,6 +204,7 @@ METADATA = {
|
|||
|
||||
PLUGIN1 = '''
|
||||
from datasette import hookimpl
|
||||
import base64
|
||||
import pint
|
||||
import json
|
||||
|
||||
|
@ -219,8 +220,14 @@ def prepare_connection(conn):
|
|||
|
||||
|
||||
@hookimpl
|
||||
def extra_css_urls():
|
||||
return ['https://example.com/app.css']
|
||||
def extra_css_urls(template, database, table, datasette):
|
||||
return ['https://example.com/{}/extra-css-urls-demo.css'.format(
|
||||
base64.b64encode(json.dumps({
|
||||
"template": template,
|
||||
"database": database,
|
||||
"table": table,
|
||||
}).encode("utf8")).decode("utf8")
|
||||
)]
|
||||
|
||||
|
||||
@hookimpl
|
||||
|
|
|
@ -2,6 +2,7 @@ from bs4 import BeautifulSoup as Soup
|
|||
from .fixtures import ( # noqa
|
||||
app_client,
|
||||
)
|
||||
import base64
|
||||
import json
|
||||
import re
|
||||
import pytest
|
||||
|
@ -15,16 +16,44 @@ def test_plugins_dir_plugin(app_client):
|
|||
assert pytest.approx(328.0839) == response.json['rows'][0][0]
|
||||
|
||||
|
||||
def test_plugin_extra_css_urls(app_client):
|
||||
response = app_client.get('/')
|
||||
@pytest.mark.parametrize(
|
||||
"path,expected_decoded_object",
|
||||
[
|
||||
(
|
||||
"/",
|
||||
{
|
||||
"template": "index.html",
|
||||
"database": None,
|
||||
"table": None,
|
||||
},
|
||||
),
|
||||
(
|
||||
"/fixtures/",
|
||||
{
|
||||
"template": "database.html",
|
||||
"database": "fixtures",
|
||||
"table": None,
|
||||
},
|
||||
),
|
||||
(
|
||||
"/fixtures/sortable",
|
||||
{
|
||||
"template": "table.html",
|
||||
"database": "fixtures",
|
||||
"table": "sortable",
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_plugin_extra_css_urls(app_client, path, expected_decoded_object):
|
||||
response = app_client.get(path)
|
||||
links = Soup(response.body, 'html.parser').findAll('link')
|
||||
assert [
|
||||
l for l in links
|
||||
if l.attrs == {
|
||||
'rel': ['stylesheet'],
|
||||
'href': 'https://example.com/app.css'
|
||||
}
|
||||
]
|
||||
special_href = [
|
||||
l for l in links if l.attrs["href"].endswith("/extra-css-urls-demo.css")
|
||||
][0]["href"]
|
||||
# This link has a base64-encoded JSON blob in it
|
||||
encoded = special_href.split("/")[3]
|
||||
assert expected_decoded_object == json.loads(base64.b64decode(encoded))
|
||||
|
||||
|
||||
def test_plugin_extra_js_urls(app_client):
|
||||
|
|
Ładowanie…
Reference in New Issue