From fd1ed3607ed7fabb9c1ba3d756f89bb1ba4d1c78 Mon Sep 17 00:00:00 2001 From: Matt Gibson Date: Tue, 18 Mar 2025 13:08:17 -0700 Subject: [PATCH] Prefer reserved word method This limits reduces the special-case searching to totally isolated reserved-word strings. All directed search behavior starts with a reserved word and has a defined syntax. --- libs/common/src/vault/search/ast.ts | 6 +++--- .../src/vault/search/bitwarden-query-grammar.ne | 3 ++- .../src/vault/search/bitwarden-query-grammar.spec.ts | 4 ++-- .../src/vault/search/bitwarden-query-grammar.ts | 11 +++++++---- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/libs/common/src/vault/search/ast.ts b/libs/common/src/vault/search/ast.ts index 8f31940ad80..da35c94456e 100644 --- a/libs/common/src/vault/search/ast.ts +++ b/libs/common/src/vault/search/ast.ts @@ -5,7 +5,7 @@ export const AstNodeTypeNames = [ "and", "or", "term", - "field term", + "fieldTerm", "hasAttachment", "hasUri", "hasFolder", @@ -109,13 +109,13 @@ export function isTerm(x: AstNode): x is Term { } export type FieldTerm = AstNodeBase & { - type: "field term"; + type: "fieldTerm"; field: string; term: string; }; export function isFieldTerm(x: AstNode): x is FieldTerm { - return x.type === "field term"; + return x.type === "fieldTerm"; } export type HasAttachment = AstNodeBase & { diff --git a/libs/common/src/vault/search/bitwarden-query-grammar.ne b/libs/common/src/vault/search/bitwarden-query-grammar.ne index 72bc24ee958..395b3b601b8 100644 --- a/libs/common/src/vault/search/bitwarden-query-grammar.ne +++ b/libs/common/src/vault/search/bitwarden-query-grammar.ne @@ -12,6 +12,7 @@ let lexer = moo.compile({ rparen: ')', // Right parenthesis // Special search functions // Note, there have been issues with reserverd words in the past, so we're using a prefix + func_field: 'field:', func_has: 'has:', func_in: 'in:', func_is: 'is:', @@ -45,7 +46,7 @@ TERM -> # naked string search term, search all fields %string {% function(d) { const start = d[0].offset; const end = d[0].offset + d[0].value.length; return { type: 'term', value: d[0].value, start, end, length: d[0].value.length } } %} # specified field search term - | %string %access %string {% function(d) { const start = d[0].offset; const end = d[2].offset + d[2].value.length; return { type: 'field term', field: d[0].value, term: d[2].value, start, end, length: end - start + 1 } } %} + | %func_field %string %access %string {% function(d) { const start = d[0].offset; const end = d[3].offset + d[3].value.length; return { type: 'fieldTerm', field: d[1].value, term: d[3].value, start, end, length: end - start + 1 } } %} # only items with attachments | %func_has "attachment" {% function(d) { const start = d[0].offset; const length = 14; return { type: 'hasAttachment', start, end: d[0].offset + length, length } } %} # only items with URIs diff --git a/libs/common/src/vault/search/bitwarden-query-grammar.spec.ts b/libs/common/src/vault/search/bitwarden-query-grammar.spec.ts index 4f7123a3421..edf18bb5cb2 100644 --- a/libs/common/src/vault/search/bitwarden-query-grammar.spec.ts +++ b/libs/common/src/vault/search/bitwarden-query-grammar.spec.ts @@ -134,11 +134,11 @@ const Parenthesis = { }; const QuotedFieldTerm = { - query: '"custom field":fizz', + query: 'field:"custom field":fizz', expectedResults: [ { contents: { - type: "field term", + type: "fieldTerm", field: '"custom field"', term: "fizz", }, diff --git a/libs/common/src/vault/search/bitwarden-query-grammar.ts b/libs/common/src/vault/search/bitwarden-query-grammar.ts index 917ff2b7793..04892fbd1d3 100644 --- a/libs/common/src/vault/search/bitwarden-query-grammar.ts +++ b/libs/common/src/vault/search/bitwarden-query-grammar.ts @@ -10,6 +10,7 @@ declare var rparen: any; declare var AND: any; declare var OR: any; declare var string: any; +declare var func_field: any; declare var access: any; declare var func_has: any; declare var func_in: any; @@ -33,6 +34,7 @@ let lexer = moo.compile({ rparen: ")", // Right parenthesis // Special search functions // Note, there have been issues with reserverd words in the past, so we're using a prefix + func_field: "field:", func_has: "has:", func_in: "in:", func_is: "is:", @@ -165,17 +167,18 @@ const grammar: Grammar = { { name: "TERM", symbols: [ + lexer.has("func_field") ? { type: "func_field" } : func_field, lexer.has("string") ? { type: "string" } : string, lexer.has("access") ? { type: "access" } : access, lexer.has("string") ? { type: "string" } : string, ], postprocess: function (d) { const start = d[0].offset; - const end = d[2].offset + d[2].value.length; + const end = d[3].offset + d[3].value.length; return { - type: "field term", - field: d[0].value, - term: d[2].value, + type: "fieldTerm", + field: d[1].value, + term: d[3].value, start, end, length: end - start + 1,