diff options
| author | Mohamed Bassem <me@mbassem.com> | 2026-02-08 15:53:14 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-08 15:53:14 +0000 |
| commit | b05a7531b76d580fc2378d3fed12f57e5f4b35b1 (patch) | |
| tree | c80d578507321ebe43f540649daba2bdec47f939 /packages/shared | |
| parent | 960ca9b67915408f26b825886f2b6c6481a658dc (diff) | |
| download | karakeep-b05a7531b76d580fc2378d3fed12f57e5f4b35b1.tar.zst | |
feat: add source filter to query language (#2465)
* feat: add source filter to query language
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* autocomplete source
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'packages/shared')
| -rw-r--r-- | packages/shared/searchQueryParser.test.ts | 36 | ||||
| -rw-r--r-- | packages/shared/searchQueryParser.ts | 24 | ||||
| -rw-r--r-- | packages/shared/types/search.ts | 10 |
3 files changed, 67 insertions, 3 deletions
diff --git a/packages/shared/searchQueryParser.test.ts b/packages/shared/searchQueryParser.test.ts index 3954e871..37275284 100644 --- a/packages/shared/searchQueryParser.test.ts +++ b/packages/shared/searchQueryParser.test.ts @@ -332,6 +332,42 @@ describe("Search Query Parser", () => { inverse: true, }, }); + expect(parseSearchQuery("source:rss")).toEqual({ + result: "full", + text: "", + matcher: { + type: "source", + source: "rss", + inverse: false, + }, + }); + expect(parseSearchQuery("-source:rss")).toEqual({ + result: "full", + text: "", + matcher: { + type: "source", + source: "rss", + inverse: true, + }, + }); + expect(parseSearchQuery("source:web")).toEqual({ + result: "full", + text: "", + matcher: { + type: "source", + source: "web", + inverse: false, + }, + }); + expect(parseSearchQuery("-source:web")).toEqual({ + result: "full", + text: "", + matcher: { + type: "source", + source: "web", + inverse: true, + }, + }); }); test("! negation alias for -", () => { // ! should work exactly like - for negation diff --git a/packages/shared/searchQueryParser.ts b/packages/shared/searchQueryParser.ts index 027a662f..7eb3b185 100644 --- a/packages/shared/searchQueryParser.ts +++ b/packages/shared/searchQueryParser.ts @@ -16,7 +16,7 @@ import { } from "typescript-parsec"; import { z } from "zod"; -import { BookmarkTypes } from "./types/bookmarks"; +import { BookmarkTypes, zBookmarkSourceSchema } from "./types/bookmarks"; import { Matcher } from "./types/search"; import { parseRelativeDate } from "./utils/relativeDateUtils"; @@ -42,7 +42,10 @@ const lexerRules: [RegExp, TokenType][] = [ [/^\s+or/i, TokenType.Or], [/^#/, TokenType.Hash], - [/^(is|url|list|after|before|age|feed|title|tag):/, TokenType.Qualifier], + [ + /^(is|url|list|after|before|age|feed|title|tag|source):/, + TokenType.Qualifier, + ], [/^"([^"]+)"/, TokenType.StringLiteral], @@ -230,6 +233,23 @@ MATCHER.setPattern( inverse: !!minus, }, }; + case "source:": { + const parsed = zBookmarkSourceSchema.safeParse(ident); + if (!parsed.success) { + return { + text: (minus?.text ?? "") + qualifier.text + ident, + matcher: undefined, + }; + } + return { + text: "", + matcher: { + type: "source", + source: parsed.data, + inverse: !!minus, + }, + }; + } case "after:": try { return { diff --git a/packages/shared/types/search.ts b/packages/shared/types/search.ts index c29270b8..b653d883 100644 --- a/packages/shared/types/search.ts +++ b/packages/shared/types/search.ts @@ -1,6 +1,6 @@ import { z } from "zod"; -import { BookmarkTypes } from "./bookmarks"; +import { BookmarkTypes, zBookmarkSourceSchema } from "./bookmarks"; const zTagNameMatcher = z.object({ type: z.literal("tagName"), @@ -88,6 +88,12 @@ const zBrokenLinksMatcher = z.object({ brokenLinks: z.boolean(), }); +const zSourceMatcher = z.object({ + type: z.literal("source"), + source: zBookmarkSourceSchema, + inverse: z.boolean(), +}); + const zNonRecursiveMatcher = z.union([ zTagNameMatcher, zListNameMatcher, @@ -103,6 +109,7 @@ const zNonRecursiveMatcher = z.union([ zTypeMatcher, zRssFeedNameMatcher, zBrokenLinksMatcher, + zSourceMatcher, ]); type NonRecursiveMatcher = z.infer<typeof zNonRecursiveMatcher>; @@ -127,6 +134,7 @@ export const zMatcherSchema: z.ZodType<Matcher> = z.lazy(() => { zTypeMatcher, zRssFeedNameMatcher, zBrokenLinksMatcher, + zSourceMatcher, z.object({ type: z.literal("and"), matchers: z.array(zMatcherSchema), |
