Skip to content

Quicklinks search: treat "&" and "and" (and multilingual equivalents) as equivalent tokens #424

@digitalby

Description

@digitalby

Bug: Quicklinks search does not treat & and and (or multilingual equivalents) as the same token

Description

The Quicklinks Explorer search uses a plain includes() comparison after toLowerCase(). This means & and its word equivalents (e.g. and) are treated as completely different strings, so a user cannot find a quicklink by substituting one for the other.

A concrete example already in the dataset: "Search B&H". None of the following queries match it today:

  • b and h
  • b & h (spacing mismatch)
  • b und h

Steps to Reproduce

  1. Open https://ray.so/quicklinks
  2. Type b and h in the search box
  3. Observe that "Search B&H" does not appear in results

Expected Behavior

Searching b and h, b&h, b und h, or any other "and" equivalent should match "Search B&H".

More broadly, the following tokens should all be treated as equivalent to & during search:

Token Language / Note
and English
adn English typo
und German
oraz Polish
i Polish, Croatian, Swedish
e Italian, Portuguese, Spanish
и Russian, Ukrainian

Actual Behavior

Only an exact substring match works. b and h does not match B&H and vice versa.

Proposed Fix

Add a normalizer that maps each token to a canonical form before comparison. A token-splitting approach handles Unicode scripts correctly (regex \b word boundaries do not work for Cyrillic, etc.):

const AND_TOKENS = new Set(["&", "and", "adn", "und", "oraz", "и", "e", "i"]);

function normalizeSearch(str: string): string {
  return str
    .toLowerCase()
    .split(/\s+/)
    .map((token) => (AND_TOKENS.has(token) ? "&" : token))
    .join(" ")
    .trim();
}

Then replace all filter call sites from:

quicklink.name.toLowerCase().includes(search.toLowerCase())

to:

normalizeSearch(quicklink.name).includes(normalizeSearch(search))

AND_TOKENS is a plain Set that can be extended with more languages or typos over time without touching the comparison logic.

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