diff --git a/packages/search/src/parser.ts b/packages/search/src/parser.ts index 80d869c..7071478 100644 --- a/packages/search/src/parser.ts +++ b/packages/search/src/parser.ts @@ -15,7 +15,15 @@ export function parse_query(q: string): Record { const result: Record = {}; for (const match of matches) { - if (/[=:]/.test(match)) { + if (/^["\s]/.test(match) && /["\s]$/.test(match)) { + const stripped = match.replace(/^["\s]|["\s]$/g, ""); + + if ("_" in result) { + result._.push(stripped); + } else { + result._ = [stripped]; + } + } else if (/[=:]/.test(match)) { const [key, value] = match.split(/[:=]/, 2); const stripped = value.replace(/^["\s]|["\s]$/g, ""); diff --git a/packages/search/tests/parse-query.test.ts b/packages/search/tests/parse-query.test.ts new file mode 100644 index 0000000..69a4562 --- /dev/null +++ b/packages/search/tests/parse-query.test.ts @@ -0,0 +1,39 @@ +import { parse_query } from "../src"; + +describe("parse query", () => { + it("should recognize key:value", () => { + const q = parse_query("foo:bar"); + expect(q.foo).toEqual(["bar"]); + }); + + it("should recognize key=value", () => { + const q = parse_query("foo=bar"); + expect(q.foo).toEqual(["bar"]); + }); + + it("should recognize key:\"value with spaces\"", () => { + const q = parse_query("foo:\"bar baz\""); + expect(q.foo).toEqual(["bar baz"]); + }); + + it("should recognize key=\"value with spaces\"", () => { + const q = parse_query("foo=\"bar baz\""); + expect(q.foo).toEqual(["bar baz"]); + }); + + it("should collect wild value", () => { + const q = parse_query("foo bar baz"); + expect(q._.sort()).toEqual(["foo", "bar", "baz"].sort()); + }); + + it("should collect \"wild value with spaces\"", () => { + const q = parse_query("foo \"bar baz\""); + expect(q._.sort()).toEqual(["foo", "bar baz"].sort()); + }); + + it("should escape `=` inside quotes", () => { + const q = parse_query("\"foo=bar\""); + expect(q).not.toHaveProperty("foo"); + expect(q._).toEqual(["foo=bar"]); + }); +});