fix(web): Fix issue where quotes cannot be used within a query (#629)
Some checks are pending
Publish to ghcr / build (linux/amd64, blacksmith-4vcpu-ubuntu-2404) (push) Waiting to run
Publish to ghcr / build (linux/arm64, blacksmith-8vcpu-ubuntu-2204-arm) (push) Waiting to run
Publish to ghcr / merge (push) Blocked by required conditions
Update Roadmap Released / update (push) Waiting to run

This commit is contained in:
Brendan Kellam 2025-11-25 12:06:51 -08:00 committed by GitHub
parent 8e036a340f
commit c962fdd636
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 106 additions and 73 deletions

View file

@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Fixed
- Fixed issue where single quotes could not be used in search queries. [#629](https://github.com/sourcebot-dev/sourcebot/pull/629)
## [4.10.0] - 2025-11-24 ## [4.10.0] - 2025-11-24
### Added ### Added

View file

@ -1,6 +1,6 @@
// This file was generated by lezer-generator. You probably shouldn't edit it. // This file was generated by lezer-generator. You probably shouldn't edit it.
export const export const
negate = 22, negate = 23,
Program = 1, Program = 1,
OrExpr = 2, OrExpr = 2,
AndExpr = 3, AndExpr = 3,
@ -18,4 +18,5 @@ export const
SymExpr = 15, SymExpr = 15,
RepoSetExpr = 16, RepoSetExpr = 16,
ParenExpr = 17, ParenExpr = 17,
Term = 18 QuotedTerm = 18,
Term = 19

File diff suppressed because one or more lines are too long

View file

@ -24,12 +24,13 @@ expr {
NegateExpr | NegateExpr |
ParenExpr | ParenExpr |
PrefixExpr | PrefixExpr |
QuotedTerm |
Term Term
} }
NegateExpr { !negate negate (PrefixExpr | ParenExpr) } NegateExpr { !negate negate (PrefixExpr | ParenExpr) }
ParenExpr { "(" query ")" } ParenExpr { "(" query? ")" }
PrefixExpr { PrefixExpr {
ArchivedExpr | ArchivedExpr |
@ -63,7 +64,8 @@ archivedValue { "yes" | "no" | "only" }
forkValue { "yes" | "no" | "only" } forkValue { "yes" | "no" | "only" }
visibilityValue { "public" | "private" | "any" } visibilityValue { "public" | "private" | "any" }
Term { quotedString | word } QuotedTerm { quotedString }
Term { word }
value { quotedString | word } value { quotedString | word }
@ -86,9 +88,7 @@ value { quotedString | word }
quotedString { '"' (!["\\\n] | "\\" _)* '"' } quotedString { '"' (!["\\\n] | "\\" _)* '"' }
// Allow almost anything in a word except spaces, parens, quotes word { (![ \t\n()]) (![ \t\n():] | ":" | "-")* }
// Colons and dashes are allowed anywhere in words (including at the start)
word { (![ \t\n()"]) (![ \t\n()":] | ":" | "-")* }
space { $[ \t\n]+ } space { $[ \t\n]+ }

View file

@ -4,7 +4,7 @@
==> ==>
Program(ParenExpr(Term(⚠))) Program(ParenExpr)
# Simple grouping # Simple grouping

View file

@ -12,7 +12,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Dash in middle # Dash in middle
@ -244,7 +244,7 @@ Program(NegateExpr(ParenExpr(AndExpr(PrefixExpr(FileExpr),PrefixExpr(LangExpr)))
==> ==>
Program(NegateExpr(ParenExpr(Term(⚠)))) Program(NegateExpr(ParenExpr))
# Negate with space after dash # Negate with space after dash

View file

@ -36,7 +36,7 @@ Program(OrExpr(Term,NegateExpr(PrefixExpr(FileExpr))))
==> ==>
Program(OrExpr(Term,Term)) Program(OrExpr(QuotedTerm,QuotedTerm))
# OR with different prefixes # OR with different prefixes
@ -260,7 +260,7 @@ Program(OrExpr(PrefixExpr(FileExpr),PrefixExpr(FileExpr)))
==> ==>
Program(OrExpr(ParenExpr(Term(⚠)),ParenExpr(Term(⚠)))) Program(OrExpr(ParenExpr,ParenExpr))
# OR with negated groups # OR with negated groups

View file

@ -156,7 +156,7 @@ Program(AndExpr(ParenExpr(OrExpr(Term,Term)),ParenExpr(OrExpr(Term,Term))))
==> ==>
Program(Term) Program(QuotedTerm)
# Prefix with OR value doesn't split # Prefix with OR value doesn't split
@ -188,7 +188,7 @@ Program(OrExpr(Term,ParenExpr(AndExpr(Term,Term))))
==> ==>
Program(OrExpr(ParenExpr(Term(⚠)),AndExpr(Term,Term))) Program(OrExpr(ParenExpr,AndExpr(Term,Term)))
# Negation of empty group # Negation of empty group
@ -196,5 +196,5 @@ Program(OrExpr(ParenExpr(Term(⚠)),AndExpr(Term,Term)))
==> ==>
Program(AndExpr(NegateExpr(ParenExpr(Term(⚠))),Term)) Program(AndExpr(NegateExpr(ParenExpr),Term))

View file

@ -4,6 +4,22 @@
==> ==>
Program(QuotedTerm)
# Leading unclosed quote
"hello
==>
Program(Term)
# Trailing unclosed quote
hello"
==>
Program(Term) Program(Term)
# Quoted string with spaces # Quoted string with spaces
@ -12,7 +28,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Multiple words in quotes # Multiple words in quotes
@ -20,7 +36,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with escaped quote # Quoted string with escaped quote
@ -28,7 +44,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with escaped backslash # Quoted string with escaped backslash
@ -36,7 +52,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Double backslash # Double backslash
@ -44,7 +60,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Multiple escaped quotes # Multiple escaped quotes
@ -52,7 +68,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Mixed escaped characters # Mixed escaped characters
@ -60,7 +76,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Empty quoted string # Empty quoted string
@ -68,7 +84,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with only spaces # Quoted string with only spaces
@ -76,7 +92,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string in file prefix # Quoted string in file prefix
@ -116,7 +132,7 @@ Program(PrefixExpr(RevisionExpr))
==> ==>
Program(AndExpr(Term,Term)) Program(AndExpr(QuotedTerm,QuotedTerm))
# Quoted and unquoted mixed # Quoted and unquoted mixed
@ -124,7 +140,7 @@ unquoted "quoted string" another
==> ==>
Program(AndExpr(Term,Term,Term)) Program(AndExpr(Term,QuotedTerm,Term))
# Quoted string with parentheses inside # Quoted string with parentheses inside
@ -132,7 +148,7 @@ Program(AndExpr(Term,Term,Term))
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with brackets # Quoted string with brackets
@ -140,7 +156,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with special chars # Quoted string with special chars
@ -148,7 +164,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with colons # Quoted string with colons
@ -156,7 +172,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with dashes # Quoted string with dashes
@ -164,7 +180,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with dots # Quoted string with dots
@ -172,7 +188,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with regex pattern # Quoted string with regex pattern
@ -180,7 +196,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with forward slashes # Quoted string with forward slashes
@ -188,7 +204,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with underscores # Quoted string with underscores
@ -196,7 +212,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with numbers # Quoted string with numbers
@ -204,7 +220,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with mixed case # Quoted string with mixed case
@ -212,7 +228,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted prefix value with spaces # Quoted prefix value with spaces
@ -236,7 +252,7 @@ Program(AndExpr(PrefixExpr(FileExpr),PrefixExpr(RepoExpr)))
==> ==>
Program(ParenExpr(Term)) Program(ParenExpr(QuotedTerm))
# Multiple quoted in parentheses # Multiple quoted in parentheses
@ -244,7 +260,7 @@ Program(ParenExpr(Term))
==> ==>
Program(ParenExpr(AndExpr(Term,Term))) Program(ParenExpr(AndExpr(QuotedTerm,QuotedTerm)))
# Quoted with escaped newline # Quoted with escaped newline
@ -252,7 +268,7 @@ Program(ParenExpr(AndExpr(Term,Term)))
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted with tab character # Quoted with tab character
@ -260,7 +276,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Lang prefix with quoted value # Lang prefix with quoted value
@ -292,7 +308,7 @@ Program(PrefixExpr(ContentExpr))
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with hash # Quoted string with hash
@ -300,7 +316,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with dollar sign # Quoted string with dollar sign
@ -308,7 +324,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with percent # Quoted string with percent
@ -316,7 +332,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with ampersand # Quoted string with ampersand
@ -324,7 +340,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with asterisk # Quoted string with asterisk
@ -332,7 +348,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with plus # Quoted string with plus
@ -340,7 +356,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with equals # Quoted string with equals
@ -348,7 +364,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with angle brackets # Quoted string with angle brackets
@ -356,7 +372,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with pipe # Quoted string with pipe
@ -364,7 +380,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with tilde # Quoted string with tilde
@ -372,7 +388,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with backtick # Quoted string with backtick
@ -380,7 +396,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with question mark # Quoted string with question mark
@ -388,7 +404,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with exclamation # Quoted string with exclamation
@ -396,7 +412,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with semicolon # Quoted string with semicolon
@ -404,7 +420,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted string with comma # Quoted string with comma
@ -412,7 +428,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Multiple quotes in content # Multiple quotes in content
@ -428,7 +444,7 @@ Program(PrefixExpr(ContentExpr))
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted file prefix as literal # Quoted file prefix as literal
@ -436,7 +452,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted lang prefix as literal # Quoted lang prefix as literal
@ -444,7 +460,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted partial prefix # Quoted partial prefix
@ -452,7 +468,7 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Mix of quoted prefix and real prefix # Mix of quoted prefix and real prefix
@ -460,7 +476,7 @@ Program(Term)
==> ==>
Program(AndExpr(Term,PrefixExpr(FileExpr))) Program(AndExpr(QuotedTerm,PrefixExpr(FileExpr)))
# Quoted short form prefix # Quoted short form prefix
@ -468,7 +484,7 @@ Program(AndExpr(Term,PrefixExpr(FileExpr)))
==> ==>
Program(Term) Program(QuotedTerm)
# Quoted revision prefix # Quoted revision prefix
@ -476,4 +492,12 @@ Program(Term)
==> ==>
Program(Term) Program(QuotedTerm)
# Quotes can be used within words
name\s*=\s*"projectmanagementlugapi lang:HCL
==>
Program(AndExpr(Term, PrefixExpr(LangExpr)))

View file

@ -18,6 +18,7 @@ import {
SymExpr, SymExpr,
SyntaxNode, SyntaxNode,
Term, Term,
QuotedTerm,
Tree, Tree,
VisibilityExpr, VisibilityExpr,
} from '@sourcebot/query-language'; } from '@sourcebot/query-language';
@ -175,8 +176,12 @@ const transformTreeToIR = async ({
// PrefixExpr contains specific prefix types // PrefixExpr contains specific prefix types
return transformPrefixExpr(node); return transformPrefixExpr(node);
case QuotedTerm:
case Term: { case Term: {
const termText = input.substring(node.from, node.to).replace(/^"|"$/g, ''); const fullText = input.substring(node.from, node.to);
// If the term is quoted, then we remove the quotes as they are
// not interpreted.
const termText = node.type.id === QuotedTerm ? fullText.replace(/^"|"$/g, '') : fullText;
return isRegexEnabled ? { return isRegexEnabled ? {
regexp: { regexp: {