From f40c83e48dcc491e664fd057565c45000234b7d5 Mon Sep 17 00:00:00 2001 From: Istvan Soos Date: Mon, 18 Nov 2024 17:35:03 +0100 Subject: [PATCH 1/4] baseline tests --- .../test/search/search_form_test.dart | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pkg/_pub_shared/test/search/search_form_test.dart b/pkg/_pub_shared/test/search/search_form_test.dart index 85504c7a38..7e7851efb4 100644 --- a/pkg/_pub_shared/test/search/search_form_test.dart +++ b/pkg/_pub_shared/test/search/search_form_test.dart @@ -199,6 +199,22 @@ void main() { expect(query.parsedQuery.tagsPredicate.toQueryParameters(), ['publisher:example.com']); }); + + test('text + topic with tag prefix', () { + final query = SearchForm(query: 'abc topic:xyz'); + final pq = query.parsedQuery; + expect(pq.text, 'abc'); + expect(pq.tagsPredicate.toQueryParameters(), ['topic:xyz']); + expect(pq.toString(), 'topic:xyz abc'); + }); + + test('text + topic with hash prefix', () { + final query = SearchForm(query: 'abc #xyz'); + final pq = query.parsedQuery; + expect(pq.text, 'abc #xyz'); + expect(pq.tagsPredicate.toQueryParameters(), []); + expect(pq.toString(), 'abc #xyz'); + }); }); group('Search URLs', () { From f7b27921eb77f749e7295676b682eeec0de4560a Mon Sep 17 00:00:00 2001 From: Istvan Soos Date: Mon, 18 Nov 2024 17:35:03 +0100 Subject: [PATCH 2/4] Updated parsing and and serialization for topic # --- pkg/_pub_shared/lib/search/search_form.dart | 29 ++++++++++++++++--- .../test/search/search_form_test.dart | 23 +++++++++++++-- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/pkg/_pub_shared/lib/search/search_form.dart b/pkg/_pub_shared/lib/search/search_form.dart index a773152e35..d88b706db0 100644 --- a/pkg/_pub_shared/lib/search/search_form.dart +++ b/pkg/_pub_shared/lib/search/search_form.dart @@ -18,6 +18,7 @@ final _sortRegExp = RegExp('sort:([a-z]+)'); final _updatedRegExp = RegExp('updated:([0-9][0-9a-z]*)'); final _tagRegExp = RegExp(r'([\+|\-]?[a-z0-9]+:[a-z0-9\-_\.]+)', caseSensitive: false); +final _topicRegExp = RegExp(r'([\+|\-])?#([a-z0-9-]{2,32})'); /// The tag prefixes that we can detect in the user-provided search query. final _detectedTagPrefixes = { @@ -152,6 +153,10 @@ class TagsPredicate { } else if (tag.startsWith('+')) { tag = tag.substring(1); } + + if (tag.startsWith('#')) { + tag = 'topic:${tag.substring(1)}'; + } p._values[tag] = required; } return p; @@ -222,7 +227,13 @@ class TagsPredicate { /// Returns the list of tag values that can be passed to search service URL. List toQueryParameters() { - return _values.entries.map((e) => e.value ? e.key : '-${e.key}').toList(); + return _values.entries.map((e) { + var tag = e.key; + if (tag.startsWith('topic:')) { + tag = '#${tag.substring(6)}'; + } + return e.value ? tag : '-$tag'; + }).toList(); } } @@ -263,10 +274,14 @@ class ParsedQueryText { queryText = queryText.replaceFirst(_packageRegexp, ' '); } - List extractRegExp(RegExp regExp, {bool Function(String?)? where}) { + List extractRegExp( + RegExp regExp, { + bool Function(String?)? where, + String? Function(Match m)? matchMapFn, + }) { final values = regExp .allMatches(queryText!) - .map((Match m) => m.group(1)) + .map((Match m) => matchMapFn == null ? m.group(1) : matchMapFn(m)) .where((s) => where == null || where(s)) .cast() .toList(); @@ -289,7 +304,13 @@ class ParsedQueryText { _tagRegExp, where: (tag) => _detectedTagPrefixes.any((p) => tag!.startsWith(p)), ); - final tagsPredicate = TagsPredicate.parseQueryValues(tagValues); + final topicValues = extractRegExp(_topicRegExp, matchMapFn: (m) { + final sign = m.group(1) ?? ''; + final value = m.group(2); + return '${sign}topic:$value'; + }); + final tagsPredicate = + TagsPredicate.parseQueryValues([...tagValues, ...topicValues]); queryText = queryText!.replaceAll(_whitespacesRegExp, ' ').trim(); if (queryText!.isEmpty) { diff --git a/pkg/_pub_shared/test/search/search_form_test.dart b/pkg/_pub_shared/test/search/search_form_test.dart index 7e7851efb4..2f8b5ee2a7 100644 --- a/pkg/_pub_shared/test/search/search_form_test.dart +++ b/pkg/_pub_shared/test/search/search_form_test.dart @@ -211,9 +211,26 @@ void main() { test('text + topic with hash prefix', () { final query = SearchForm(query: 'abc #xyz'); final pq = query.parsedQuery; - expect(pq.text, 'abc #xyz'); - expect(pq.tagsPredicate.toQueryParameters(), []); - expect(pq.toString(), 'abc #xyz'); + expect(pq.text, 'abc'); + expect(pq.tagsPredicate.toQueryParameters(), ['#xyz']); + expect(pq.tagsPredicate.matches(['topic:xyz']), true); + expect(pq.tagsPredicate.matches(['topic:abc']), false); + expect(pq.toString(), '#xyz abc'); + }); + + test('negative hash is parsed', () { + final query = SearchForm(query: '-#abc'); + final pq = query.parsedQuery; + expect(pq.tagsPredicate.toQueryParameters(), ['-#abc']); + expect(pq.tagsPredicate.matches(['topic:xyz']), true); + expect(pq.tagsPredicate.matches(['topic:abc']), false); + expect(pq.toString(), '-#abc'); + }); + + test('negative tag predicate in the serialization parsing', () { + final tp = TagsPredicate.parseQueryValues(['-#abc']); + expect(tp.matches(['topic:abc']), false); + expect(tp.matches(['topic:xyz']), true); }); }); From 2875825ccfb02b06408e2c78d1ee78e530caa0c2 Mon Sep 17 00:00:00 2001 From: Istvan Soos Date: Tue, 19 Nov 2024 10:47:55 +0100 Subject: [PATCH 3/4] fix regexp --- pkg/_pub_shared/lib/search/search_form.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/_pub_shared/lib/search/search_form.dart b/pkg/_pub_shared/lib/search/search_form.dart index d88b706db0..33c60d686b 100644 --- a/pkg/_pub_shared/lib/search/search_form.dart +++ b/pkg/_pub_shared/lib/search/search_form.dart @@ -17,8 +17,8 @@ final RegExp _allDependencyRegExp = final _sortRegExp = RegExp('sort:([a-z]+)'); final _updatedRegExp = RegExp('updated:([0-9][0-9a-z]*)'); final _tagRegExp = - RegExp(r'([\+|\-]?[a-z0-9]+:[a-z0-9\-_\.]+)', caseSensitive: false); -final _topicRegExp = RegExp(r'([\+|\-])?#([a-z0-9-]{2,32})'); + RegExp(r'([\+\-]?[a-z0-9]+:[a-z0-9\-_\.]+)', caseSensitive: false); +final _topicRegExp = RegExp(r'([\+\-])?#([a-z0-9-]{2,32})'); /// The tag prefixes that we can detect in the user-provided search query. final _detectedTagPrefixes = { From 571716a45a66374db94b7afd37f6fdb502834606 Mon Sep 17 00:00:00 2001 From: Istvan Soos Date: Tue, 19 Nov 2024 11:43:40 +0100 Subject: [PATCH 4/4] Do not do canonicalization yet --- pkg/_pub_shared/lib/search/search_form.dart | 5 +---- pkg/_pub_shared/test/search/search_form_test.dart | 8 ++++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/pkg/_pub_shared/lib/search/search_form.dart b/pkg/_pub_shared/lib/search/search_form.dart index 33c60d686b..198a6c9590 100644 --- a/pkg/_pub_shared/lib/search/search_form.dart +++ b/pkg/_pub_shared/lib/search/search_form.dart @@ -228,10 +228,7 @@ class TagsPredicate { /// Returns the list of tag values that can be passed to search service URL. List toQueryParameters() { return _values.entries.map((e) { - var tag = e.key; - if (tag.startsWith('topic:')) { - tag = '#${tag.substring(6)}'; - } + final tag = e.key; return e.value ? tag : '-$tag'; }).toList(); } diff --git a/pkg/_pub_shared/test/search/search_form_test.dart b/pkg/_pub_shared/test/search/search_form_test.dart index 2f8b5ee2a7..e7e498cceb 100644 --- a/pkg/_pub_shared/test/search/search_form_test.dart +++ b/pkg/_pub_shared/test/search/search_form_test.dart @@ -212,19 +212,19 @@ void main() { final query = SearchForm(query: 'abc #xyz'); final pq = query.parsedQuery; expect(pq.text, 'abc'); - expect(pq.tagsPredicate.toQueryParameters(), ['#xyz']); + expect(pq.tagsPredicate.toQueryParameters(), ['topic:xyz']); expect(pq.tagsPredicate.matches(['topic:xyz']), true); expect(pq.tagsPredicate.matches(['topic:abc']), false); - expect(pq.toString(), '#xyz abc'); + expect(pq.toString(), 'topic:xyz abc'); }); test('negative hash is parsed', () { final query = SearchForm(query: '-#abc'); final pq = query.parsedQuery; - expect(pq.tagsPredicate.toQueryParameters(), ['-#abc']); + expect(pq.tagsPredicate.toQueryParameters(), ['-topic:abc']); expect(pq.tagsPredicate.matches(['topic:xyz']), true); expect(pq.tagsPredicate.matches(['topic:abc']), false); - expect(pq.toString(), '-#abc'); + expect(pq.toString(), '-topic:abc'); }); test('negative tag predicate in the serialization parsing', () {