aboutsummaryrefslogtreecommitdiffstats
path: root/packages/shared
diff options
context:
space:
mode:
authorMohamed Bassem <me@mbassem.com>2025-09-13 21:37:56 +0100
committerGitHub <noreply@github.com>2025-09-13 21:37:56 +0100
commita92ada7727b2596414aafe204e5001eb066569cb (patch)
tree73e289791f83135dfa2f5cecc6fa1c4019679238 /packages/shared
parent3bae3aad9a62dbf2cc9a0038c90ea992166cc336 (diff)
downloadkarakeep-a92ada7727b2596414aafe204e5001eb066569cb.tar.zst
feat(search): add title search qualifier (#1940)
* fix(search): include link titles in title matcher * docs(search): add title qualifier * docs: remove title qualifier from v0.27 guide
Diffstat (limited to 'packages/shared')
-rw-r--r--packages/shared/searchQueryParser.test.ts36
-rw-r--r--packages/shared/searchQueryParser.ts7
-rw-r--r--packages/shared/types/search.ts8
3 files changed, 50 insertions, 1 deletions
diff --git a/packages/shared/searchQueryParser.test.ts b/packages/shared/searchQueryParser.test.ts
index 7a86ecb5..3fe3f388 100644
--- a/packages/shared/searchQueryParser.test.ts
+++ b/packages/shared/searchQueryParser.test.ts
@@ -162,6 +162,42 @@ describe("Search Query Parser", () => {
inverse: true,
},
});
+ expect(parseSearchQuery("title:example")).toEqual({
+ result: "full",
+ text: "",
+ matcher: {
+ type: "title",
+ title: "example",
+ inverse: false,
+ },
+ });
+ expect(parseSearchQuery("-title:example")).toEqual({
+ result: "full",
+ text: "",
+ matcher: {
+ type: "title",
+ title: "example",
+ inverse: true,
+ },
+ });
+ expect(parseSearchQuery('title:"my title"')).toEqual({
+ result: "full",
+ text: "",
+ matcher: {
+ type: "title",
+ title: "my title",
+ inverse: false,
+ },
+ });
+ expect(parseSearchQuery('-title:"my title"')).toEqual({
+ result: "full",
+ text: "",
+ matcher: {
+ type: "title",
+ title: "my title",
+ inverse: true,
+ },
+ });
expect(parseSearchQuery("#my-tag")).toEqual({
result: "full",
text: "",
diff --git a/packages/shared/searchQueryParser.ts b/packages/shared/searchQueryParser.ts
index 9a29a8b7..f919df96 100644
--- a/packages/shared/searchQueryParser.ts
+++ b/packages/shared/searchQueryParser.ts
@@ -41,7 +41,7 @@ const lexerRules: [RegExp, TokenType][] = [
[/^\s+or/i, TokenType.Or],
[/^#/, TokenType.Hash],
- [/^(is|url|list|after|before|age|feed):/, TokenType.Qualifier],
+ [/^(is|url|list|after|before|age|feed|title):/, TokenType.Qualifier],
[/^"([^"]+)"/, TokenType.StringLiteral],
@@ -195,6 +195,11 @@ MATCHER.setPattern(
text: "",
matcher: { type: "url", url: ident, inverse: !!minus },
};
+ case "title:":
+ return {
+ text: "",
+ matcher: { type: "title", title: ident, inverse: !!minus },
+ };
case "#":
return {
text: "",
diff --git a/packages/shared/types/search.ts b/packages/shared/types/search.ts
index 26d5bd42..caedcf94 100644
--- a/packages/shared/types/search.ts
+++ b/packages/shared/types/search.ts
@@ -31,6 +31,12 @@ const zUrlMatcher = z.object({
inverse: z.boolean(),
});
+const zTitleMatcher = z.object({
+ type: z.literal("title"),
+ title: z.string(),
+ inverse: z.boolean(),
+});
+
const zFavouritedMatcher = z.object({
type: z.literal("favourited"),
favourited: z.boolean(),
@@ -82,6 +88,7 @@ const zNonRecursiveMatcher = z.union([
zListNameMatcher,
zArchivedMatcher,
zUrlMatcher,
+ zTitleMatcher,
zFavouritedMatcher,
zDateAfterMatcher,
zDateBeforeMatcher,
@@ -104,6 +111,7 @@ export const zMatcherSchema: z.ZodType<Matcher> = z.lazy(() => {
zListNameMatcher,
zArchivedMatcher,
zUrlMatcher,
+ zTitleMatcher,
zFavouritedMatcher,
zDateAfterMatcher,
zDateBeforeMatcher,