Skip to content

Clear all discards the search term when the term contains an ampersand #3977

Description

@alexvishweb

Describe the current behavior

On a search results page, "Remove all" / "Clear all" silently discards the search
term when the term contains an ampersand (or <, >, " or '), returning the entire
catalogue instead of the filtered search.

snippets/facets.liquid:26 builds the clear-all URL from the search term with
escape, an HTML escaper, rather than a URL encoder:

assign terms = results.terms | escape
assign results_url = '?q=' | append: terms | append: '&options%5Bprefix%5D=last&sort_by=' | append: sort_by

escape turns & into &, which the browser decodes back to a real & when it
resolves the href, splitting the query string.

Steps to reproduce, on a clean Dawn install with the sample catalogue:

  1. Search for a & b -> /search?q=a+%26+b&options%5Bprefix%5D=last (3 results)
  2. Apply any filter, e.g. Availability: In stock (2 results)
  3. Click "Remove all"

Result: the URL becomes

?q=a%20&%20b&options%5Bprefix%5D=last&sort_by=relevance

Note the bare & mid-term: q is now a and b is a separate valueless
parameter. The page returns 45 results - the whole catalogue - and the filter row
switches to catalogue-wide facets (Region, Colour, Volume) instead of the
search's own.

Two details worth flagging:

  • The search input still displays a & b throughout, so the UI asserts a term
    the result set does not reflect. There is no error state; the shopper simply
    gets the wrong products under a correct-looking query.
  • On the broken URL, search.terms and the result set disagree, and what the
    box renders varies by theme. The reliable test is the result count, not the
    displayed term.

Describe the expected behavior

"Remove all" clears the filters and preserves the search term:

?q=a+%26+b&options%5Bprefix%5D=last&sort_by=relevance

returning the same 3 results as step 1.

Version information (Dawn, browsers and operating systems)

  • Dawn Version: 16.0.0
  • Edge Version: 152.0.4191.66 (Official build) (64-bit)
  • Windows 11

Possible solution

url_encode alone is not sufficient, because search.terms is returned already
HTML-escaped and Liquid's escape is escape-once. Evidence:
{{ search.terms | size }} returns 16 for a typed tweed & wool (12 characters),
and the term a&b<c>d"e'f comes back as a&amp;b&lt;c&gt;d&quot;e&#39;f. So
url_encode on its own yields a%26amp%3Bb... - the entity encoded rather than
the character - and repeated clicks compound it (&amp; -> &amp;amp;).

Unwinding the entities before encoding, with the ampersand last so earlier
replacements cannot be re-read, does round-trip correctly:

assign terms = results.terms | replace: '&lt;', '<' | replace: '&gt;', '>' | replace: '&quot;', '"' | replace: '&#39;', "'" | replace: '&amp;', '&' | url_encode

That is a workaround rather than a fix. The underlying issue is that the clear-all
URL has to be rebuilt by hand at all: Liquid exposes no request query string, and
a search has no equivalent of a collection's results.url. Horizon already avoids
hand-built URLs everywhere else by using the platform-generated
value.url_to_remove / filter.url_to_remove; a url_to_remove equivalent for
"clear everything", or an exposed search URL, would remove the need for any
escaping logic here.

Additional context/screenshots

The same construction is present verbatim in Horizon
(blocks/filters.liquid:59-63), where results_url feeds clear-all in five
places, so the fix likely wants applying in both themes. Horizon has issues
disabled, hence reporting here.

Related but distinct: #2198 covered the drawer 'Clear' action clearing all
filters rather than one group, and was closed in January 2023. This is the
query-string encoding of the clear-all URL, not the scope of the action.
Reproduced on Dawn 16.0.0 (current release, v16.0.0 / theme_version 16.0.0).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions