msfl_visitors 1.2.0 → 1.2.1.dev0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/msfl_visitors/visitor.rb +18 -4
- data/msfl_visitors.gemspec +1 -1
- data/spec/msfl_visitors/visitor_spec.rb +16 -0
- data/spec/msfl_visitors/visitors/chewy_term_filter_spec.rb +50 -49
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e43425b31d0774b6b7bfef7b7a47dd8914195729
|
4
|
+
data.tar.gz: b3fdf922ea429c522a77258ca40e5955d53373f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc796e4b08f79201048cf37715f50cba54abc9026ebbb96669a5c8f4b3e8ef93505a65e2f5e1790494d3775521a65bfdcb30092ba1c7d1fffec329855684a8e7
|
7
|
+
data.tar.gz: 142acb13b5679b278a9c2487ecace20e8917d3673a715b9ecbfa91ee1ea5ab71f131a49a2237851cdb50855e28b1ee8aa1468a831b548736eeb0700b02ffaa09
|
@@ -49,6 +49,13 @@ module MSFLVisitors
|
|
49
49
|
[{clause: root.accept(self)}].concat(clauses).reject { |c| c[:clause] == "" }
|
50
50
|
end
|
51
51
|
|
52
|
+
# Note that the ES documentation also indicates that # is a special character that requires
|
53
|
+
# escaping and that this behavior is not part of the PERL regex; however Ruby automatically escapes
|
54
|
+
# literal hashes when constructing regices
|
55
|
+
def escape_es_special_regex_chars(str)
|
56
|
+
str.gsub(/([@&<>~])/) { |m| "\\#{m}" }
|
57
|
+
end
|
58
|
+
|
52
59
|
private
|
53
60
|
|
54
61
|
attr_reader :mode
|
@@ -68,12 +75,19 @@ module MSFLVisitors
|
|
68
75
|
Nodes::Match => '=~',
|
69
76
|
}
|
70
77
|
|
78
|
+
def escaped_regex_helper(escaped_str)
|
79
|
+
exp = visitor.escape_es_special_regex_chars "#{escaped_str}"
|
80
|
+
# why you must use #inspect, not #to_s. @link http://ruby-doc.org/core-1.9.3/Regexp.html#method-i-3D-7E
|
81
|
+
%r[.*#{exp}.*]
|
82
|
+
end
|
83
|
+
|
71
84
|
def visit(node)
|
72
85
|
case node
|
73
86
|
when Nodes::Field
|
74
87
|
node.value.to_s
|
75
88
|
when Nodes::Regex
|
76
|
-
|
89
|
+
esc = Regexp.escape("#{node.value.to_s}")
|
90
|
+
escaped_regex_helper esc
|
77
91
|
when Nodes::Word
|
78
92
|
"\"#{node.value}\""
|
79
93
|
when Nodes::Date, Nodes::Time
|
@@ -86,10 +100,10 @@ module MSFLVisitors
|
|
86
100
|
|
87
101
|
when Nodes::Match
|
88
102
|
if node.right.is_a? Nodes::Set
|
89
|
-
|
90
|
-
"#{node.left.accept(visitor)} #{BINARY_OPERATORS[node.class]}
|
103
|
+
escaped_str = node.right.contents.map { |right_child| MSFLVisitors::Nodes::Regex.new(right_child.value.to_s).accept(visitor).inspect[3..-4] }.join('|')
|
104
|
+
"#{node.left.accept(visitor)} #{BINARY_OPERATORS[node.class]} " + escaped_regex_helper(escaped_str).inspect
|
91
105
|
else
|
92
|
-
"#{node.left.accept(visitor)} #{BINARY_OPERATORS[node.class]}
|
106
|
+
"#{node.left.accept(visitor)} #{BINARY_OPERATORS[node.class]} " + MSFLVisitors::Nodes::Regex.new(node.right.value.to_s).accept(visitor).inspect
|
93
107
|
end
|
94
108
|
when Nodes::Containment,
|
95
109
|
Nodes::GreaterThan,
|
data/msfl_visitors.gemspec
CHANGED
@@ -11,4 +11,20 @@ describe MSFLVisitors::Visitor do
|
|
11
11
|
expect(subject.send(:mode)).to eq :term
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
15
|
+
describe "#escape_es_special_regex_chars" do
|
16
|
+
|
17
|
+
{
|
18
|
+
'ab@cd' => 'ab\@cd',
|
19
|
+
'ab&cd' => 'ab\&cd',
|
20
|
+
'ab<cd' => 'ab\<cd',
|
21
|
+
'ab>cd' => 'ab\>cd',
|
22
|
+
'ab~cd' => 'ab\~cd',
|
23
|
+
}.each do |str, expected|
|
24
|
+
|
25
|
+
it "escapes '#{str}' as '#{expected}'" do
|
26
|
+
expect(MSFLVisitors::Visitor.new.escape_es_special_regex_chars str).to eq expected
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
14
30
|
end
|
@@ -198,12 +198,23 @@ describe MSFLVisitors::Visitor do
|
|
198
198
|
|
199
199
|
describe "a Regex node" do
|
200
200
|
|
201
|
-
let(:node) { MSFLVisitors::Nodes::Regex.new
|
201
|
+
let(:node) { MSFLVisitors::Nodes::Regex.new regex }
|
202
|
+
|
203
|
+
let(:regex) { "foobar" }
|
202
204
|
|
203
205
|
context "when using the TermFilter visitor" do
|
204
206
|
|
205
|
-
it "results in:
|
206
|
-
expect(result).to eq
|
207
|
+
it "results in: /.*foobar.*/" do
|
208
|
+
expect(result).to eq /.*foobar.*/
|
209
|
+
end
|
210
|
+
|
211
|
+
context "when the node requires escaping" do
|
212
|
+
|
213
|
+
let(:node) { MSFLVisitors::Nodes::Regex.new "foo*bar" }
|
214
|
+
|
215
|
+
it "results in: #{/.*foo\*bar.*/.inspect}" do
|
216
|
+
expect(result).to eq /.*foo\*bar.*/
|
217
|
+
end
|
207
218
|
end
|
208
219
|
end
|
209
220
|
|
@@ -215,6 +226,36 @@ describe MSFLVisitors::Visitor do
|
|
215
226
|
expect(result).to eq "foobar"
|
216
227
|
end
|
217
228
|
end
|
229
|
+
|
230
|
+
context "when the expression contains `#`, `@`, `&`, `<`, `>`, or `~`" do
|
231
|
+
|
232
|
+
let(:regex) { "a #sentence@ contain&ing <lucene> cha~rs" }
|
233
|
+
|
234
|
+
it "escapes lucene specific special characters" do
|
235
|
+
expected = /.*a\ \#sentence\@\ contain\&ing\ \<lucene\>\ cha\~rs.*/
|
236
|
+
expect(result).to eq expected
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
context "when the regex contains characters that require escaping" do
|
241
|
+
|
242
|
+
let(:regex) { 'this / needs to % {be,escaped} *. ^[or] | \else' }
|
243
|
+
|
244
|
+
let(:node) { MSFLVisitors::Nodes::Regex.new regex }
|
245
|
+
|
246
|
+
it "returns: #{/.*this\ \/\ needs\ to\ %\ \{be,escaped\}\ \*\.\ \^\[or\]\ \|\ \\else.*/.inspect}" do
|
247
|
+
expect(result).to eq /.*this\ \/\ needs\ to\ %\ \{be,escaped\}\ \*\.\ \^\[or\]\ \|\ \\else.*/
|
248
|
+
end
|
249
|
+
|
250
|
+
context "when using the Aggregations visitor" do
|
251
|
+
|
252
|
+
before { visitor.mode = :aggregations }
|
253
|
+
|
254
|
+
it "returns: 'this\\ /\\ needs\\ to\\ %\\ \\{be,escaped\\}\\ \\*\\.\\ \\^\\[or\\]\\ \\|\\ \\\\else'" do
|
255
|
+
expect(result).to eq "this\\ /\\ needs\\ to\\ %\\ \\{be,escaped\\}\\ \\*\\.\\ \\^\\[or\\]\\ \\|\\ \\\\else"
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
218
259
|
end
|
219
260
|
|
220
261
|
describe "a Match node" do
|
@@ -223,8 +264,8 @@ describe MSFLVisitors::Visitor do
|
|
223
264
|
|
224
265
|
context "when using the TermFilter visitor" do
|
225
266
|
|
226
|
-
it "results in: 'left =~
|
227
|
-
expect(result).to eq %(lhs =~
|
267
|
+
it "results in: 'left =~ /.*rhs.*/'" do
|
268
|
+
expect(result).to eq %(lhs =~ /.*rhs.*/)
|
228
269
|
end
|
229
270
|
end
|
230
271
|
|
@@ -243,8 +284,8 @@ describe MSFLVisitors::Visitor do
|
|
243
284
|
|
244
285
|
context "when using the TermFilter visitor" do
|
245
286
|
|
246
|
-
it "results in: 'left =~
|
247
|
-
expect(result).to eq %(lhs =~
|
287
|
+
it "results in: 'left =~ /.*this\ \(needs\)\ to\ be\*\ escaped.*/'" do
|
288
|
+
expect(result).to eq %(lhs =~ ) + /.*this\ \(needs\)\ to\ be\*\ escaped.*/.inspect
|
248
289
|
end
|
249
290
|
end
|
250
291
|
|
@@ -262,8 +303,8 @@ describe MSFLVisitors::Visitor do
|
|
262
303
|
|
263
304
|
context "when using the TermFilter visitor" do
|
264
305
|
|
265
|
-
it "results in: 'left =~
|
266
|
-
expect(result).to eq %(lhs =~
|
306
|
+
it "results in: 'left =~ /.*foo|bar|baz.*/'" do
|
307
|
+
expect(result).to eq %(lhs =~ ) + /.*foo|bar|baz.*/.inspect
|
267
308
|
end
|
268
309
|
end
|
269
310
|
|
@@ -719,46 +760,6 @@ describe MSFLVisitors::Visitor do
|
|
719
760
|
end
|
720
761
|
end
|
721
762
|
end
|
722
|
-
|
723
|
-
describe "a Regex node" do
|
724
|
-
|
725
|
-
let(:regex) { "content" }
|
726
|
-
|
727
|
-
let(:node) { MSFLVisitors::Nodes::Regex.new regex }
|
728
|
-
|
729
|
-
it "returns: 'Regexp.new( '.*' + Regexp.escape( \"content\" ) + '.*' )'" do
|
730
|
-
expect(result).to eq %(Regexp.new( '.*' + Regexp.escape( "#{regex}" ) + '.*' ))
|
731
|
-
end
|
732
|
-
|
733
|
-
context "when using the Aggregations visitor" do
|
734
|
-
|
735
|
-
before { visitor.mode = :aggregations }
|
736
|
-
|
737
|
-
it "returns: the elasticsearch regular expression formatted string \"content\"" do
|
738
|
-
expect(result).to eq "#{regex}"
|
739
|
-
end
|
740
|
-
end
|
741
|
-
|
742
|
-
context "when the regex contains characters that require escaping" do
|
743
|
-
|
744
|
-
let(:regex) { 'this / needs to % {be,escaped} *. ^[or] | \else' }
|
745
|
-
|
746
|
-
let(:node) { MSFLVisitors::Nodes::Regex.new regex }
|
747
|
-
|
748
|
-
it "returns: 'Regexp.new( '.*' + Regexp.escape( \"this / needs to % {be,escaped} *. ^[or] | \\else\" ) + '.*' )'" do
|
749
|
-
expect(result).to eq %(Regexp.new( '.*' + Regexp.escape( "this / needs to % {be,escaped} *. ^[or] | \\else" ) + '.*' ))
|
750
|
-
end
|
751
|
-
|
752
|
-
context "when using the Aggregations visitor" do
|
753
|
-
|
754
|
-
before { visitor.mode = :aggregations }
|
755
|
-
|
756
|
-
it "returns: 'this\\ /\\ needs\\ to\\ %\\ \\{be,escaped\\}\\ \\*\\.\\ \\^\\[or\\]\\ \\|\\ \\\\else'" do
|
757
|
-
expect(result).to eq "this\\ /\\ needs\\ to\\ %\\ \\{be,escaped\\}\\ \\*\\.\\ \\^\\[or\\]\\ \\|\\ \\\\else"
|
758
|
-
end
|
759
|
-
end
|
760
|
-
end
|
761
|
-
end
|
762
763
|
end
|
763
764
|
|
764
765
|
describe "range value nodes" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: msfl_visitors
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.1.dev0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Courtland Caldwell
|
@@ -173,9 +173,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
173
173
|
version: '0'
|
174
174
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
175
175
|
requirements:
|
176
|
-
- - "
|
176
|
+
- - ">"
|
177
177
|
- !ruby/object:Gem::Version
|
178
|
-
version:
|
178
|
+
version: 1.3.1
|
179
179
|
requirements: []
|
180
180
|
rubyforge_project:
|
181
181
|
rubygems_version: 2.2.2
|