fix(autocomplete): parse kind:rest in /api/tags/search

The add-tag input lets the user type 'character:mocha' as a kind shortcut,
but the autocomplete was passing the whole query through to ilike, so
'%character:mocha%' never matched any display_name. Use parse_kind_prefix
to split the prefix into a kind filter, leaving the rest as the search
term. An explicit ?kind= (e.g. fandom picker) still wins. Empty rest
('character:') falls into the no-query branch and shows top characters.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-25 19:53:42 -04:00
parent 667a70acb9
commit f3094ec24f
+14 -1
View File
@@ -663,13 +663,26 @@ def search_tags():
- kind: filter to only include tags of this kind
"""
from sqlalchemy import case
from app.utils.tag_prefix import parse_kind_prefix
query = request.args.get("q", "").strip().lower()
raw_q = request.args.get("q", "").strip()
limit = request.args.get("limit", 10, type=int)
exclude_kind = request.args.get("exclude_kind", "").strip()
exclude_kinds = [k.strip() for k in exclude_kind.split(",") if k.strip()]
include_kind = request.args.get("kind", "").strip()
# Honour the same `kind:rest` shortcut the add-tag input uses, so typing
# "character:mocha" filters to character rows matching "mocha" instead of
# ilike-matching the literal "character:" string against display_name.
# An explicit ?kind= still wins (used by the fandom picker).
if not include_kind:
parsed_kind, parsed_rest = parse_kind_prefix(raw_q)
if parsed_kind is not None:
include_kind = parsed_kind
raw_q = parsed_rest
query = raw_q.lower()
f = aliased(Tag)
display_expr = case(
(