diff --git a/datasette/default_column_types.py b/datasette/default_column_types.py index f5811aef..6def3698 100644 --- a/datasette/default_column_types.py +++ b/datasette/default_column_types.py @@ -5,7 +5,17 @@ import markupsafe from datasette import hookimpl from datasette.column_types import ColumnType, SQLiteType -from datasette.utils import is_url + +_HTTP_URL_RE = re.compile(r"https?://\S+", re.IGNORECASE) + + +def _normalize_http_url(value): + if not isinstance(value, str): + return None + normalized = value.strip() + if not _HTTP_URL_RE.fullmatch(normalized): + return None + return normalized class UrlColumnType(ColumnType): @@ -16,10 +26,10 @@ class UrlColumnType(ColumnType): async def render_cell(self, value, column, table, database, datasette, request): if not value or not isinstance(value, str): return None - stripped = value.strip() - if not is_url(stripped): - return None - escaped = markupsafe.escape(stripped) + normalized = _normalize_http_url(value) + if normalized is None: + return markupsafe.escape(value.strip()) + escaped = markupsafe.escape(normalized) return markupsafe.Markup(f'{escaped}') async def validate(self, value, datasette): @@ -27,7 +37,7 @@ class UrlColumnType(ColumnType): return None if not isinstance(value, str): return "URL must be a string" - if not re.match(r"^https?://\S+$", value.strip()): + if _normalize_http_url(value) is None: return "Invalid URL" return None