This commit is contained in:
Sebastian Cao 2026-07-15 00:51:03 +08:00 committed by GitHub
commit fcd3a3a377
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 46 additions and 2 deletions

View file

@ -5,6 +5,7 @@ import markupsafe
from datasette import hookimpl
from datasette.column_types import ColumnType, SQLiteType
from datasette.utils import truncate_url
class UrlColumnType(ColumnType):
@ -15,8 +16,12 @@ class UrlColumnType(ColumnType):
async def render_cell(self, value, column, table, database, datasette, request):
if not value or not isinstance(value, str):
return None
escaped = markupsafe.escape(value.strip())
return markupsafe.Markup(f'<a href="{escaped}">{escaped}</a>')
url = value.strip()
escaped = markupsafe.escape(url)
truncated = markupsafe.escape(
truncate_url(url, datasette.setting("truncate_cells_html"))
)
return markupsafe.Markup(f'<a href="{escaped}">{truncated}</a>')
async def validate(self, value, datasette):
if value is None or value == "":

View file

@ -107,6 +107,7 @@ The edit interface takes :ref:`custom column types <table_configuration_column_t
- Permission checks are now cached on a per-request basis, speeding up table pages with multiple plugins that check permissions in order to populate the :ref:`table actions menu <plugin_hook_table_actions>`.
- Fixed a warning about ``gen.throw(*sys.exc_info())``. (:issue:`2776`)
- New default custom column type ``textarea`` for multi-line text content. This is rendered as a ``<textarea>`` input in the edit UI.
- Links rendered by the ``url`` :ref:`custom column type <table_configuration_column_types>` now have their displayed text truncated according to the :ref:`setting_truncate_cells_html` setting, while still linking to the full URL. (:issue:`1805`)
- The ``json`` column type now implements client-side validation in the edit UI.
- The :ref:`makeColumnField() <javascript_plugins_makeColumnField>` JavaScript plugin hook allows plugins to define custom fields in the edit interface for their custom column types.
- New UI for inserting, editing, and deleting rows within Datasette. (:issue:`2780`)

View file

@ -568,6 +568,44 @@ async def test_url_render_cell(ds_ct):
assert "https://example.com" in rendered["website"]
@pytest.mark.asyncio
async def test_url_render_cell_truncates(tmp_path_factory):
# truncate_cells_html should also truncate the displayed text of url
# column type links, while keeping the full URL in the href - refs #1805
db_directory = tmp_path_factory.mktemp("dbs")
db_path = str(db_directory / "data.db")
db = sqlite3.connect(db_path)
db.execute("create table posts (id integer primary key, website text)")
long_url = (
"https://images.openfoodfacts.org/images/products/000/000/000/088/"
"nutrition_fr.5.200.jpg"
)
db.execute("insert into posts values (1, ?)", [long_url])
db.commit()
db.close()
ds = Datasette(
[db_path],
settings={"truncate_cells_html": 30},
config={
"databases": {
"data": {"tables": {"posts": {"column_types": {"website": "url"}}}}
}
},
)
await ds.invoke_startup()
response = await ds.client.get("/data/posts.json?_extra=render_cell")
assert response.status_code == 200
rendered = response.json()["render_cell"][0]["website"]
# The full URL is preserved in the href
assert f'href="{long_url}"' in rendered
# ...but the visible link text is truncated
soup = Soup(rendered, "html.parser")
link_text = soup.find("a").text
assert link_text != long_url
assert "" in link_text
ds.close()
@pytest.mark.asyncio
async def test_email_render_cell(ds_ct):
await ds_ct.invoke_startup()