core: normalize special separators in fuzzy search (#9541)

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
This commit is contained in:
01zulfi
2026-03-24 09:50:27 +05:00
committed by GitHub
parent d48643cbb9
commit 9628a940e9
2 changed files with 41 additions and 1 deletions

View File

@@ -93,4 +93,25 @@ describe("lookup.fuzzy", () => {
).toStrictEqual([{ id: "1", title: "hello-suffix" }]);
});
});
describe("separator normalization", () => {
const items = [
{ id: "1", title: "file search.jpg" },
{ id: "2", title: "file-search.jpg" },
{ id: "3", title: "file_search.jpg" }
];
test("query with space matches all separator variants", () => {
const result = fuzzy("file search", items, (i) => i.id, { title: 1 });
expect(result).toStrictEqual(items);
});
test("query with special character between words matches all separator variants", () => {
let result = fuzzy("file_search", items, (i) => i.id, { title: 1 });
expect(result).toStrictEqual(items);
result = fuzzy("file-search", items, (i) => i.id, { title: 1 });
expect(result).toStrictEqual(items);
});
});
});

View File

@@ -20,6 +20,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { match, surround } from "fuzzyjs";
import { clone } from "./clone.js";
const SEPARATORS = /(?<=\w)[^a-zA-Z0-9](?=\w)/g;
function normalizeSeparators(str: string): string {
return str.replace(SEPARATORS, " ");
}
function hasSeparator(str: string): boolean {
const result = SEPARATORS.test(str);
SEPARATORS.lastIndex = 0;
return result;
}
export function fuzzy<T>(
query: string,
items: T[],
@@ -39,13 +51,20 @@ export function fuzzy<T>(
}
> = new Map();
const shouldNormalize = hasSeparator(query);
const finalQuery = shouldNormalize ? normalizeSeparators(query) : query;
for (const item of items) {
if (options.limit && results.size >= options.limit) break;
const identifier = getIdentifier(item);
for (const field in fields) {
const result = match(query, `${item[field]}`);
const value = `${item[field]}`;
const result = match(
finalQuery,
shouldNormalize ? normalizeSeparators(value) : value
);
if (!result.match) continue;
const oldMatch = results.get(identifier);