{"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1460988975", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1460988975, "node_id": "IC_kwDOBm6k_c5XFOwv", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-03-08T22:42:57Z", "updated_at": "2023-03-08T22:42:57Z", "author_association": "OWNER", "body": "Aside idea: it might be interesting if there were \"lazy\" template variables available in the context: things that are not actually executed unless a template author requests them.\r\n\r\nImagine if `metadata` was a lazy template reference, such that custom templates that don't display any metadata don't trigger it to be resolved (which might involve additional database queries some day).", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1551694938, "label": "?_extra= support (draft)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1460759358", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1460759358, "node_id": "IC_kwDOBm6k_c5XEWs-", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-03-08T19:48:13Z", "updated_at": "2023-03-20T18:47:12Z", "author_association": "OWNER", "body": "Breaking this down into smaller steps:\r\n\r\n- [x] Get `?_next=` working\r\n- [x] Implement extensions - so `.json` is needed again for the JSON version, and anything without an extension is passed through a new code path for HTML\r\n- [ ] That HTML view should only access JSON data, which can be seen by using `.context` - this will require a lot of updates to templates (it may be necessary to still provide access to some helper functions though). This will form the basis of the ambition to fully document the template context.\r\n- [ ] Get a bunch of the existing table HTML and JSON tests to pass\r\n- [ ] Use those tests to refactor the nasty `_next` code, see https://github.com/simonw/datasette/pull/1999#issuecomment-1460905469\r\n- [ ] Figure out how the [register_output_renderer(datasette)](https://docs.datasette.io/en/stable/plugin_hooks.html#register-output-renderer-datasette) plugin hook should work", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1551694938, "label": "?_extra= support (draft)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1476781401", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1476781401, "node_id": "IC_kwDOBm6k_c5YBeVZ", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-03-20T19:01:35Z", "updated_at": "2023-03-20T19:01:35Z", "author_association": "OWNER", "body": "Down to just these failures:\r\n```\r\nFAILED tests/test_table_html.py::test_sort_links - AssertionError: assert [{'attrs': {'class': ['col-Link'], 'scope': 'col', 'data-column': 'Link', 'data-column-type': '', 'data-column-not-null': '0', 'data-is-pk': '0'}, 'a_href': None}, {'attrs': {'class': ['col-pk1'], 'scope': 'col', 'data-column': 'pk1', 'data-column-typ...\r\nFAILED tests/test_table_html.py::test_table_html_simple_primary_key - AssertionError: assert 'id\\xa0\u25bc' == 'id'\r\nFAILED tests/test_table_html.py::test_table_csv_json_export_interface - AssertionError: assert ['/fixtures/simple_primary_key.json?id__gt=2', '/fixtures/simple_primary_key.testall?id__gt=2', '/fixtures/simple_primary_key.testnone?id__gt=2', '/fixtures/simple_primary_key.testresponse?id__gt=2', '/fixtures/simple_primary_key.csv?id__gt=2&_size=ma...\r\nFAILED tests/test_table_html.py::test_csv_json_export_links_include_labels_if_foreign_keys - AssertionError: assert ['/fixtures/facetable.json?_labels=on', '/fixtures/facetable.testall?_labels=on', '/fixtures/facetable.testnone?_labels=on', '/fixtures/facetable.testresponse?_labels=on', '/fixtures/facetable.csv?_labels=on&_size=max', '#export'] == ['/', '', '#export']\r\nFAILED tests/test_table_html.py::test_rowid_sortable_no_primary_key - AssertionError: assert 'rowid\\xa0\u25bc' == 'rowid'\r\nFAILED tests/test_table_html.py::test_table_html_filter_form_column_options[/fixtures/infinity-expected_column_options0] - AssertionError: assert ['- column -', 'rowid', 'value'] == ['- column -']\r\nFAILED tests/test_table_html.py::test_table_html_filter_form_column_options[/fixtures/primary_key_multiple_columns-expected_column_options1] - AssertionError: assert ['- column -', 'id', 'content', 'content2'] == ['- column -']\r\nFAILED tests/test_table_html.py::test_table_html_filter_form_column_options[/fixtures/compound_primary_key-expected_column_options2] - AssertionError: assert ['- column -', 'pk1', 'pk2', 'content'] == ['- column -']\r\nFAILED tests/test_table_html.py::test_table_html_filter_form_still_shows_nocol_columns - AssertionError: assert ['- column -'] == ['- column -', 'pk1', 'pk2', 'content', 'sortable_with_nulls', 'sortable_with_nulls_2', 'text', 'sortable']\r\nFAILED tests/test_table_html.py::test_metadata_sort - AssertionError: assert ['id', 'name\\xa0\u25bc'] == ['id', 'name']\r\nFAILED tests/test_table_html.py::test_metadata_sort_desc - AssertionError: assert ['pk\\xa0\u25b2', 'name'] == ['pk', 'name']\r\n=== 11 failed, 57 passed in 7.59s ===\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1551694938, "label": "?_extra= support (draft)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1460986533", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1460986533, "node_id": "IC_kwDOBm6k_c5XFOKl", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-03-08T22:40:28Z", "updated_at": "2023-03-08T22:40:28Z", "author_association": "OWNER", "body": "Figuring out what to do with `display_columns_and_rows()` is hard. That returns rows as this special kind of object, which is designed to be accessed from the HTML templates:\r\n\r\nhttps://github.com/simonw/datasette/blob/96e94f9b7b2db53865e61390bcce6761727f26d8/datasette/views/table.py#L45-L71", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1551694938, "label": "?_extra= support (draft)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1460970807", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1460970807, "node_id": "IC_kwDOBm6k_c5XFKU3", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-03-08T22:31:49Z", "updated_at": "2023-03-08T22:33:03Z", "author_association": "OWNER", "body": "For the HTML version, I need to decide where all of the stuff that happens in `async def extra_template()` is going to live.\r\n\r\nI think it's another one of those extra functions, triggered for `?_extra=context`.\r\n\r\nhttps://github.com/simonw/datasette/blob/96e94f9b7b2db53865e61390bcce6761727f26d8/datasette/views/table.py#L813-L912", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1551694938, "label": "?_extra= support (draft)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1462997800", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1462997800, "node_id": "IC_kwDOBm6k_c5XM5Mo", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-03-09T23:39:47Z", "updated_at": "2023-03-09T23:39:47Z", "author_association": "OWNER", "body": "Found a neat trick:\r\n```diff\r\ndiff --git a/datasette/app.py b/datasette/app.py\r\nindex 186f192d..40416713 100644\r\n--- a/datasette/app.py\r\n+++ b/datasette/app.py\r\n@@ -23,7 +23,13 @@ from pathlib import Path\r\n \r\n from markupsafe import Markup, escape\r\n from itsdangerous import URLSafeSerializer\r\n-from jinja2 import ChoiceLoader, Environment, FileSystemLoader, PrefixLoader\r\n+from jinja2 import (\r\n+ ChoiceLoader,\r\n+ Environment,\r\n+ FileSystemLoader,\r\n+ PrefixLoader,\r\n+ StrictUndefined,\r\n+)\r\n from jinja2.environment import Template\r\n from jinja2.exceptions import TemplateNotFound\r\n \r\n@@ -394,7 +400,10 @@ class Datasette:\r\n ]\r\n )\r\n self.jinja_env = Environment(\r\n- loader=template_loader, autoescape=True, enable_async=True\r\n+ loader=template_loader,\r\n+ autoescape=True,\r\n+ enable_async=True,\r\n+ undefined=StrictUndefined,\r\n )\r\n self.jinja_env.filters[\"escape_css_string\"] = escape_css_string\r\n self.jinja_env.filters[\"quote_plus\"] = urllib.parse.quote_plus\r\n```\r\nThis causes Jinja to raise a hard error if there are any variables referenced in the template that are not available in the context.\r\n\r\nIt's helping me spot things that are still missing, rather than just relying on failed unit tests.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1551694938, "label": "?_extra= support (draft)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1480163485", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1480163485, "node_id": "IC_kwDOBm6k_c5YOYCd", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-03-22T19:48:00Z", "updated_at": "2023-03-22T19:48:00Z", "author_association": "OWNER", "body": "Getting close now! Only 13 failures left, mostly relating to CSV.\r\n```\r\nFAILED tests/test_csv.py::test_table_csv - assert 500 == 200\r\nFAILED tests/test_csv.py::test_table_csv_cors_headers - assert 500 == 200\r\nFAILED tests/test_csv.py::test_table_csv_no_header - assert 500 == 200\r\nFAILED tests/test_csv.py::test_table_csv_with_labels - assert 500 == 200\r\nFAILED tests/test_csv.py::test_table_csv_with_nullable_labels - assert 500 == 200\r\nFAILED tests/test_csv.py::test_table_csv_blob_columns - assert 500 == 200\r\nFAILED tests/test_csv.py::test_table_csv_download - assert 500 == 200\r\nFAILED tests/test_csv.py::test_table_csv_stream - assert 1 == 101\r\nFAILED tests/test_plugins.py::test_hook_extra_css_urls[/fixtures/sortable-expected_decoded_object2] - AssertionError: assert {'added': 15,...ortable', ...} == {'added': 15,...ortable', ...}\r\nFAILED tests/test_plugins.py::test_hook_register_facet_classes - KeyError: 'suggested_facets'\r\nFAILED tests/test_csv.py::test_csv_trace - AttributeError: 'NoneType' object has no attribute 'text'\r\nFAILED tests/test_plugins.py::test_hook_extra_body_script[/fixtures/sortable-expected_extra_body_script2] - AssertionError: assert {'added': 15,...ixtures', ...} == {'added': 15,...ixtures', ...}\r\nFAILED tests/test_plugins.py::test_hook_register_output_renderer_all_parameters - assert {'1+1': 2, 'c... 0xXXX>', ...} == {'1+1': 2, 'c... 0xXXX>', ...}\r\n=============== 13 failed, 1287 passed, 2 skipped, 1 xfailed in 61.57s (0:01:01) ================\r\n```\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1551694938, "label": "?_extra= support (draft)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1399343659", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1399343659, "node_id": "IC_kwDOBm6k_c5TaEor", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-01-21T22:19:20Z", "updated_at": "2023-02-06T23:02:12Z", "author_association": "OWNER", "body": "HTML mode needs a list of renderers so it can show links to `.geojson` etc - can do that as a hidden extra (maybe called `renderers`), repeating this code:\r\n\r\nhttps://github.com/simonw/datasette/blob/e4ebef082de90db4e1b8527abc0d582b7ae0bc9d/datasette/views/base.py#L477-L497", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1551694938, "label": "?_extra= support (draft)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1474704790", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1474704790, "node_id": "IC_kwDOBm6k_c5X5jWW", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-03-18T04:52:59Z", "updated_at": "2023-03-18T04:52:59Z", "author_association": "OWNER", "body": "Here are the next set of tests to get passing:\r\n```\r\n% pytest tests/test_table_api.py\r\n```\r\n```\r\nFAILED tests/test_table_api.py::test_facets[/fixtures/facetable.json?_facet=state&_facet=_city_id-expected_facet_results0] - KeyError: 'name'\r\nFAILED tests/test_table_api.py::test_facets[/fixtures/facetable.json?_facet=state&_facet=_city_id&state=MI-expected_facet_results1] - KeyError: 'name'\r\nFAILED tests/test_table_api.py::test_facets[/fixtures/facetable.json?_facet=planet_int-expected_facet_results2] - KeyError: 'name'\r\nFAILED tests/test_table_api.py::test_facets[/fixtures/facetable.json?_facet=planet_int&planet_int=1-expected_facet_results3] - KeyError: 'name'\r\nFAILED tests/test_table_api.py::test_suggested_facets - KeyError: 'suggested_facets'\r\nFAILED tests/test_table_api.py::test_allow_facet_off - KeyError: 'suggested_facets'\r\nFAILED tests/test_table_api.py::test_suggest_facets_off - KeyError: 'suggested_facets'\r\nFAILED tests/test_table_api.py::test_nofacet[True] - KeyError: 'suggested_facets'\r\nFAILED tests/test_table_api.py::test_nofacet[False] - KeyError: 'suggested_facets'\r\nFAILED tests/test_table_api.py::test_nosuggest[True] - KeyError: 'suggested_facets'\r\nFAILED tests/test_table_api.py::test_nosuggest[False] - KeyError: 'suggested_facets'\r\nFAILED tests/test_table_api.py::test_nocount[True-None] - KeyError: 'count'\r\nFAILED tests/test_table_api.py::test_nocount[False-15] - KeyError: 'count'\r\nFAILED tests/test_table_api.py::test_expand_labels - AssertionError: assert {'13': {'_cit...:00:00', ...}} == {'13': {'_cit...:00:00', ...}}\r\nFAILED tests/test_table_api.py::test_expand_label - AssertionError: assert {'1': {'forei...l': '1', ...}} == {'1': {'forei...': '1'}, ...}}\r\nFAILED tests/test_table_api.py::test_ttl_parameter[/fixtures/facetable.json-max-age=5] - KeyError: 'Cache-Control'\r\nFAILED tests/test_table_api.py::test_ttl_parameter[/fixtures/facetable.json?_ttl=invalid-max-age=5] - KeyError: 'Cache-Control'\r\nFAILED tests/test_table_api.py::test_ttl_parameter[/fixtures/facetable.json?_ttl=10-max-age=10] - KeyError: 'Cache-Control'\r\nFAILED tests/test_table_api.py::test_ttl_parameter[/fixtures/facetable.json?_ttl=0-no-cache] - KeyError: 'Cache-Control'\r\nFAILED tests/test_table_api.py::test_infinity_returned_as_null - AssertionError: assert [{'rowid': 1,...'value': 1.5}] == [{'rowid': 1,...'value': 1.5}]\r\nFAILED tests/test_table_api.py::test_null_and_compound_foreign_keys_are_not_expanded - AssertionError: assert [{'foreign_ke...': None, ...}] == [{'foreign_ke...': None, ...}]\r\nFAILED tests/test_table_api.py::test_binary_data_in_json[/fixtures/binary_data.json?_shape=array-expected_json0-None] - assert [{'data': \"b'..., 'rowid': 3}] == [{'data': {'$..., 'rowid': 3}]\r\nFAILED tests/test_table_api.py::test_binary_data_in_json[/fixtures/binary_data.json?_shape=array&_nl=on-None-{\"rowid\": 1, \"data\": {\"$base64\": true, \"encoded\": \"FRwCx60F/g==\"}}\\n{\"rowid\": 2, \"data\": {\"$base64\": true, \"encoded\": \"FRwDx60F/g==\"}}\\n{\"rowid\": 3, \"data\": null}] - assert '{\"ok\": false...title\": null}' == '{\"rowid\": 1,...\"data\": null}'\r\nFAILED tests/test_table_api.py::test_paginate_using_link_header[] - assert 1 == 21\r\nFAILED tests/test_table_api.py::test_paginate_using_link_header[?_shape=arrays] - assert 1 == 21\r\nFAILED tests/test_table_api.py::test_paginate_using_link_header[?_shape=arrayfirst] - assert 400 == 200\r\nFAILED tests/test_table_api.py::test_paginate_using_link_header[?_shape=object] - assert 1 == 21\r\nFAILED tests/test_table_api.py::test_paginate_using_link_header[?_shape=objects] - assert 1 == 21\r\nFAILED tests/test_table_api.py::test_paginate_using_link_header[?_shape=array] - assert 1 == 21\r\nFAILED tests/test_table_api.py::test_paginate_using_link_header[?_shape=array&_nl=on] - assert 1 == 21\r\nFAILED tests/test_table_api.py::test_col_nocol[/fixtures/facetable.json?_col=created-expected_columns0] - KeyError: 'columns'\r\nFAILED tests/test_table_api.py::test_col_nocol[/fixtures/facetable.json?_nocol=created-expected_columns1] - KeyError: 'columns'\r\nFAILED tests/test_table_api.py::test_col_nocol[/fixtures/facetable.json?_col=state&_col=created-expected_columns2] - KeyError: 'columns'\r\nFAILED tests/test_table_api.py::test_col_nocol[/fixtures/facetable.json?_col=state&_col=state-expected_columns3] - KeyError: 'columns'\r\nFAILED tests/test_table_api.py::test_col_nocol[/fixtures/facetable.json?_col=state&_col=created&_nocol=created-expected_columns4] - KeyError: 'columns'\r\nFAILED tests/test_table_api.py::test_col_nocol[/fixtures/facetable.json?_nocol=state&_facet=state-expected_columns5] - KeyError: 'columns'\r\nFAILED tests/test_table_api.py::test_col_nocol[/fixtures/simple_view.json?_nocol=content-expected_columns6] - KeyError: 'columns'\r\nFAILED tests/test_table_api.py::test_col_nocol[/fixtures/simple_view.json?_col=content-expected_columns7] - KeyError: 'columns'\r\n============================================================================= 38 failed, 73 passed, 1 xfailed in 7.25s =============================================================================\r\n```\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1551694938, "label": "?_extra= support (draft)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1463023674", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1463023674, "node_id": "IC_kwDOBm6k_c5XM_g6", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-03-10T00:16:03Z", "updated_at": "2023-03-10T00:16:03Z", "author_association": "OWNER", "body": "I also need to figure out the `renderers` stuff, so I can link to the right URLs for CSV and JSON and other formats:\r\n\r\nhttps://github.com/simonw/datasette/blob/6d07a7da1531cd749844fc6827d9a1e57009b2ea/datasette/views/base.py#L474-L518", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1551694938, "label": "?_extra= support (draft)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1480339527", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1480339527, "node_id": "IC_kwDOBm6k_c5YPDBH", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-03-22T22:28:54Z", "updated_at": "2023-03-22T22:28:54Z", "author_association": "OWNER", "body": "I hacked at the CSV stuff until it worked.\r\n\r\nI need to clean it up though, but I can do that in this separate task:\r\n- #1101", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1551694938, "label": "?_extra= support (draft)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1475074025", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1475074025, "node_id": "IC_kwDOBm6k_c5X69fp", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-03-19T02:14:28Z", "updated_at": "2023-03-19T02:14:51Z", "author_association": "OWNER", "body": "I had to replicate quite a bit of this logic from `base.py`:\r\n\r\nhttps://github.com/simonw/datasette/blob/56b0758a5fbf85d01ff80a40c9b028469d7bb65f/datasette/views/base.py#L526-L544\r\n\r\nI should refactor this when I move the canned / arbitrary query views away from that base class too.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1551694938, "label": "?_extra= support (draft)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1461070937", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1461070937, "node_id": "IC_kwDOBm6k_c5XFixZ", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-03-09T00:18:52Z", "updated_at": "2023-03-09T00:19:36Z", "author_association": "OWNER", "body": "I managed to get HTML view working! I did it by continuing to add more things to the extras and the `_html` bundle until the page loaded for me:\r\n\r\n```diff\r\n async def extra_extras():\r\n \"Available ?_extra= blocks\"\r\n return {\r\n@@ -1981,6 +2053,14 @@ async def extra_extras():\r\n \"query\",\r\n \"display_columns\",\r\n \"display_rows\",\r\n+ \"database\",\r\n+ \"table\",\r\n+ \"database_color\",\r\n+ \"table_actions\",\r\n+ \"filters\",\r\n+ \"renderers\",\r\n+ \"custom_table_templates\",\r\n+ \"sorted_facet_results\",\r\n ]\r\n }\r\n \r\n@@ -2006,6 +2086,14 @@ async def extra_extras():\r\n extra_query,\r\n extra_metadata,\r\n extra_extras,\r\n+ extra_database,\r\n+ extra_table,\r\n+ extra_database_color,\r\n+ extra_table_actions,\r\n+ extra_filters,\r\n+ extra_renderers,\r\n+ extra_custom_table_templates,\r\n+ extra_sorted_facet_results,\r\n )\r\n```\r\nI'll probably refactor this into something cleaner, and maybe but a bunch of them in a `\"html\"` dictionary and update the templates to use `{{ html.filters }}` or similar. Will look at that once the tests are passing.\r\n\r\n\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1551694938, "label": "?_extra= support (draft)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1463005744", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1463005744, "node_id": "IC_kwDOBm6k_c5XM7Iw", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-03-09T23:52:15Z", "updated_at": "2023-03-09T23:52:23Z", "author_association": "OWNER", "body": "I need to figure out what to do about `extra_context_from_filters` - which was previously passed straight to the HTML context.\r\n\r\nhttps://github.com/simonw/datasette/blob/11f7feb7a3f7166c71389786880863d60ed3d165/datasette/views/table.py#L406-L422", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1551694938, "label": "?_extra= support (draft)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1999#issuecomment-1480179217", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1999", "id": 1480179217, "node_id": "IC_kwDOBm6k_c5YOb4R", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-03-22T19:55:31Z", "updated_at": "2023-03-22T21:34:02Z", "author_association": "OWNER", "body": "I rebased from `main`. Now:\r\n\r\n```\r\nFAILED tests/test_csv.py::test_table_csv - assert 500 == 200\r\nFAILED tests/test_csv.py::test_table_csv_cors_headers - assert 500 == 200\r\nFAILED tests/test_csv.py::test_table_csv_no_header - assert 500 == 200\r\nFAILED tests/test_csv.py::test_table_csv_with_labels - assert 500 == 200\r\nFAILED tests/test_csv.py::test_table_csv_with_nullable_labels - assert 500 == 200\r\nFAILED tests/test_csv.py::test_table_csv_blob_columns - assert 500 == 200\r\nFAILED tests/test_csv.py::test_table_csv_download - assert 500 == 200\r\nFAILED tests/test_csv.py::test_table_csv_stream - assert 1 == 101\r\nFAILED tests/test_csv.py::test_csv_trace - AttributeError: 'NoneType' object has no attribute 'text'\r\nFAILED tests/test_plugins.py::test_hook_extra_css_urls[/fixtures/sortable-expected_decoded_object2] - AssertionError: assert {'added': 15,...ortable', ...} == {'added': 15,...ortable', ...}\r\nFAILED tests/test_plugins.py::test_hook_render_cell_demo - AttributeError: 'NoneType' object has no attribute 'string'\r\nFAILED tests/test_plugins.py::test_hook_render_cell_async[/fixtures/simple_primary_key] - assert b'RENDER_CELL_ASYNC_RESULT' in b'\\n\\n
\\n{{ row[\"description\"] }} Category: {{ row.display(\"category_id\") }}