language_filter 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,10 @@
1
+ \w*fuck\w*
2
+ \w*fcuk\w*
3
+ \w*fuk\w*
4
+ \w*shit\w*
5
+ ass+(es)?
6
+ asshol\w*
7
+ bastards?
8
+ \w*bitch\w*
9
+ cunt\w*
10
+ fag\w*
@@ -1,21 +1,20 @@
1
- \w*sex\w*
1
+ sex\w*
2
2
  blow ?job\w*
3
3
  fellat\w*
4
4
  felch\w*
5
- \w*f[\b_]*[uv][\b_]*c[\b_]*k\w*
5
+ \w*fuck\w*
6
6
  wank\w*
7
- cock\w*
7
+ cocks?
8
8
  cock suck\w*
9
9
  poll ?smok\w*
10
- dick\w*
11
- dick ?suck\w*
10
+ dicks?
12
11
  fudge ?pack\w*
13
12
  rim ?job\w*
14
13
  knob ?gobbl\w*
15
- anal\w*
14
+ anal
16
15
  rectums?
17
- \w*a[s\$5z]{2}
18
- \w*a[s\$5z]{2}h[o0]l[e3]\w*
16
+ ass+
17
+ as*hole\w*
19
18
  ballsacks?
20
19
  scrotums?
21
20
  bollocks
@@ -26,12 +25,12 @@ knobends?
26
25
  manhoods?
27
26
  wieners?
28
27
  breasts?
29
- tit\w*
28
+ tit(t(ie|y))?s?
30
29
  boob\w*
31
30
  honkers?
32
31
  cleavages?
33
32
  vagina\w*
34
- puss[y(ies)(ee)]
33
+ puss(y|ies|ee)
35
34
  muffs?
36
35
  cunt\w*
37
36
  twats?
@@ -45,12 +44,13 @@ homos?
45
44
  sluts?
46
45
  whor\w*
47
46
  skank\w*
48
- g+[\b_]*h?[\b_]*[ae][\b_]*ys?
47
+ g+h?[ae]ys?
49
48
  dykes?
50
- \w*f[\b_]*a[\b_]*g\w*
51
- \w*cum\w*
49
+ fag\w*
50
+ cumm?(ing|er)
52
51
  jizz\w*
53
52
  pubes?
53
+ puberty
54
54
  pubic
55
55
  smegma
56
56
  boy ?butter
@@ -1,4 +1,4 @@
1
- stab\w*
1
+ stab(ing|ed|s|ber)?
2
2
  kill\w*
3
3
  beat ?up
4
4
  beat the \w+ out of
@@ -6,8 +6,8 @@ beat the \w+ out of
6
6
  fuck ?\w* up
7
7
  murder\w*
8
8
  genocide
9
- shoot [(him)(her)(it)(me)(us)(them)]
10
- shot [(him)(her)(it)(me)(us)(them)]
9
+ shoot (him|her|it|me|us|them)
10
+ shot (him|her|it|me|us|them)
11
11
  gun\w*
12
12
  phasers?
13
- death ?(ray)?
13
+ death( ray)?
@@ -1,172 +1,284 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'pathname'
2
- require 'yaml'
3
4
  require 'language_filter/error'
4
5
  require 'language_filter/version'
5
6
 
6
7
  module LanguageFilter
7
- class Filter
8
- attr_accessor :matchlist, :exceptionlist, :replacement
9
-
10
- DEFAULT_EXCEPTIONLIST = []
11
- DEFAULT_MATCHLIST = File.dirname(__FILE__) + "/../config/filters/profanity.txt"
12
- DEFAULT_REPLACEMENT = :stars
13
-
14
- def initialize(options={})
15
- @matchlist = if options[:matchlist] then
16
- validate_list_content(options[:matchlist])
17
- set_list_content(options[:matchlist])
18
- else set_list_content(DEFAULT_MATCHLIST) end
19
- @exceptionlist = if options[:exceptionlist] then
20
- validate_list_content(options[:exceptionlist])
21
- set_list_content(options[:exceptionlist])
22
- else set_list_content(DEFAULT_EXCEPTIONLIST) end
23
- @replacement = options[:replacement] || DEFAULT_REPLACEMENT
24
- validate_replacement
25
- end
26
-
27
- # SETTERS
28
-
29
- def matchlist=(content)
30
- validate_list_content(content)
31
- @matchlist = case content
32
- when :default then set_list_content(DEFAULT_MATCHLIST)
33
- else @matchlist = set_list_content(content)
34
- end
35
- end
36
-
37
- def exceptionlist=(content)
38
- if content == :default then
39
- @exceptionlist = set_list_content(DEFAULT_EXCEPTIONLIST)
40
- else
41
- validate_list_content(content)
42
- @exceptionlist = set_list_content(content)
43
- end
44
- end
45
-
46
- def replacement=(value)
47
- @replacement = case value
48
- when :default then :stars
49
- else value
50
- end
51
- validate_replacement
52
- end
53
-
54
- # LANGUAGE
55
-
56
- def match?(text)
57
- return false unless text.to_s.size >= 3
58
- @matchlist.each do |list_item|
59
- start_at = 0
60
- text.scan(/\b#{list_item}\b/i) do |match|
61
- match_start = text[start_at,text.size].index(/\b#{list_item}\b/i) unless @exceptionlist.empty?
62
- match_end = match_start + match.size unless @exceptionlist.empty?
63
- unless match == [nil] then
64
- return true if @exceptionlist.empty? or not protected_by_exceptionlist?(match_start,match_end,text,start_at)
65
- end
66
- start_at = match_end + 1 unless @exceptionlist.empty?
67
- end
68
- end
69
- false
70
- end
71
-
72
- def matched(text)
73
- words = []
74
- return words unless text.to_s.size >= 3
75
- @matchlist.each do |list_item|
76
- start_at = 0
77
- text.scan(/\b#{list_item}\b/i) do |match|
78
- match_start = text[start_at,text.size].index(/\b#{list_item}\b/i) unless @exceptionlist.empty?
79
- match_end = match_start + match.size unless @exceptionlist.empty?
80
- unless match == [nil] then
81
- words << match if @exceptionlist.empty? or not protected_by_exceptionlist?(match_start,match_end,text,start_at)
82
- end
83
- start_at = match_end + 1 unless @exceptionlist.empty?
84
- end
85
- end
86
- words.uniq
87
- end
88
-
89
- def sanitize(text)
90
- return text unless text.to_s.size >= 3
91
- @matchlist.each do |list_item|
92
- start_at = 0
93
- text.gsub! /\b#{list_item}\b/i do |match|
94
- match_start = text[start_at,text.size].index(/\b#{list_item}\b/i) unless @exceptionlist.empty?
95
- match_end = match_start + match.size unless @exceptionlist.empty?
96
- unless @exceptionlist.empty? or not protected_by_exceptionlist?(match_start,match_end,text,start_at) then
97
- start_at = match_end + 1 unless @exceptionlist.empty?
98
- match
99
- else
100
- start_at = match_end + 1 unless @exceptionlist.empty?
101
- replace(match)
102
- end
103
- end
104
- end
105
- text
106
- end
107
-
108
- private
109
-
110
- # VALIDATIONS
111
-
112
- def validate_list_content(content)
113
- case content
114
- when Array then content.all? {|c| c.class == String} || raise(LanguageFilter::EmptyContentList.new("List content array is empty."))
115
- when String then File.exists?(content) || raise(LanguageFilter::UnkownContentFile.new("List content file \"#{content}\" can't be found."))
116
- when Pathname then content.exist? || raise(LanguageFilter::UnkownContentFile.new("List content file \"#{content}\" can't be found."))
117
- when Symbol then
118
- case content
119
- when :default, :hate, :profanity, :sex, :violence then true
120
- else raise(LanguageFilter::UnkownContent.new("The only accepted symbols are :default, :hate, :profanity, :sex, and :violence."))
121
- end
122
- else raise LanguageFilter::UnkownContent.new("The list content can be either an Array, Pathname, or String path to a file.")
123
- end
124
- end
125
-
126
- def validate_replacement
127
- case @replacement
128
- when :default, :garbled, :vowels, :stars, :nonconsonants
129
- else raise LanguageFilter::UnknownReplacement.new("This is not a known replacement type.")
130
- end
131
- end
132
-
133
- # HELPERS
134
-
135
- def set_list_content(list)
136
- case list
137
- when :hate then load_list File.dirname(__FILE__) + "/../config/filters/hate.txt"
138
- when :profanity then load_list File.dirname(__FILE__) + "/../config/filters/profanity.txt"
139
- when :sex then load_list File.dirname(__FILE__) + "/../config/filters/sex.txt"
140
- when :violence then load_list File.dirname(__FILE__) + "/../config/filters/violence.txt"
141
- when Array then list
142
- when String, Pathname then load_list list.to_s
143
- else []
144
- end
145
- end
146
-
147
- def load_list(filepath)
148
- IO.readlines(filepath).each {|line| line.gsub!(/\n/,'')}
149
- end
150
-
151
- def protected_by_exceptionlist?(match_start,match_end,text,start_at)
152
- @exceptionlist.each do |list_item|
153
- exception_start = text[start_at,text.size].index(/\b#{list_item}\b/i)
154
- if exception_start and exception_start <= match_start then
155
- return true if exception_start + text[start_at,text.size][/\b#{list_item}\b/i].size >= match_end
156
- end
157
- end
158
- return false
159
- end
160
-
161
- # This was moved to private because users should just use sanitize for any content
162
- def replace(word)
163
- case @replacement
164
- when :vowels then word.gsub(/[aeiou]/i, '*')
165
- when :stars then '*' * word.size
166
- when :nonconsonants then word.gsub(/[^bcdfghjklmnpqrstvwxyz]/i, '*')
167
- when :default, :garbled then '$@!#%'
168
- else raise LanguageFilter::UnknownReplacement.new("#{@replacement} is not a known replacement type.")
169
- end
170
- end
171
- end
8
+ class Filter
9
+ attr_accessor :matchlist, :exceptionlist, :replacement, :creative_letters
10
+ attr_reader :creative_matchlist
11
+
12
+ CREATIVE_BEG_REGEX = '(?<=\\s|\\A|_|\\-|\\.)'
13
+ CREATIVE_END_REGEX = '(?=\\b|\\s|\\z|_|\\-|\\.)'
14
+
15
+ DEFAULT_EXCEPTIONLIST = []
16
+ DEFAULT_MATCHLIST = File.dirname(__FILE__) + "/../config/matchlists/profanity.txt"
17
+ DEFAULT_REPLACEMENT = :stars
18
+ DEFAULT_CREATIVE_LETTERS = false
19
+
20
+ def initialize(options={})
21
+ @creative_letters = if options[:creative_letters] then
22
+ options[:creative_letters]
23
+ else DEFAULT_CREATIVE_LETTERS end
24
+
25
+ @matchlist = if options[:matchlist] then
26
+ validate_list_content(options[:matchlist])
27
+ set_list_content(options[:matchlist])
28
+ else set_list_content(DEFAULT_MATCHLIST) end
29
+ @creative_matchlist = @matchlist.map {|list_item| use_creative_letters(list_item)}
30
+
31
+ @exceptionlist = if options[:exceptionlist] then
32
+ validate_list_content(options[:exceptionlist])
33
+ set_list_content(options[:exceptionlist])
34
+ elsif options[:matchlist].class == Symbol then
35
+ set_list_content(options[:matchlist],folder: "exceptionlists")
36
+ else set_list_content(DEFAULT_EXCEPTIONLIST) end
37
+
38
+ @replacement = options[:replacement] || DEFAULT_REPLACEMENT
39
+ validate_replacement
40
+ end
41
+
42
+ # SETTERS
43
+
44
+ def matchlist=(content)
45
+ validate_list_content(content)
46
+ @matchlist = case content
47
+ when :default then set_list_content(DEFAULT_MATCHLIST)
48
+ else set_list_content(content)
49
+ end
50
+ @exceptionlist = set_list_content(content,folder: "exceptionlists") if content.class == Symbol and @exceptionlist.empty?
51
+ @creative_matchlist = @matchlist.map {|list_item| use_creative_letters(list_item)}
52
+ end
53
+
54
+ def exceptionlist=(content)
55
+ validate_list_content(content)
56
+ @exceptionlist = case content
57
+ when :default then set_list_content(DEFAULT_EXCEPTIONLIST)
58
+ else set_list_content(content)
59
+ end
60
+ end
61
+
62
+ def replacement=(value)
63
+ @replacement = case value
64
+ when :default then :stars
65
+ else value
66
+ end
67
+ validate_replacement
68
+ end
69
+
70
+ # LANGUAGE
71
+
72
+ def match?(text)
73
+ return false unless text.to_s.size >= 3
74
+ chosen_matchlist = case @creative_letters
75
+ when true then @creative_matchlist
76
+ else @matchlist
77
+ end
78
+ chosen_matchlist.each do |list_item|
79
+ start_at = 0
80
+ text.scan(%r"#{beg_regex}#{list_item}#{end_regex}"i) do |match|
81
+ unless @exceptionlist.empty? then
82
+ match_start = text[start_at..-1].index(%r"#{beg_regex}#{list_item}#{end_regex}"i) + start_at
83
+ match_end = match_start + match.size-1
84
+ end
85
+ return true if @exceptionlist.empty? or not protected_by_exceptionlist?(match_start,match_end,text,start_at)
86
+ start_at = match_end + 1 unless @exceptionlist.empty?
87
+ end
88
+ end
89
+ false
90
+ end
91
+
92
+ def matched(text)
93
+ words = []
94
+ return words unless text.to_s.size >= 3
95
+ chosen_matchlist = case @creative_letters
96
+ when true then @creative_matchlist
97
+ else @matchlist
98
+ end
99
+ chosen_matchlist.each do |list_item|
100
+ start_at = 0
101
+ text.scan(%r"#{beg_regex}#{list_item}#{end_regex}"i) do |match|
102
+ unless @exceptionlist.empty? then
103
+ match_start = text[start_at..-1].index(%r"#{beg_regex}#{list_item}#{end_regex}"i) + start_at
104
+ match_end = match_start + match.size-1
105
+ end
106
+ words << match if @exceptionlist.empty? or not protected_by_exceptionlist?(match_start,match_end,text,start_at)
107
+ start_at = match_end + 1 unless @exceptionlist.empty?
108
+ end
109
+ end
110
+ words.uniq
111
+ end
112
+
113
+ def sanitize(text)
114
+ return text unless text.to_s.size >= 3
115
+ chosen_matchlist = case @creative_letters
116
+ when true then @creative_matchlist
117
+ else @matchlist
118
+ end
119
+ chosen_matchlist.each do |list_item|
120
+ start_at = 0
121
+ text.gsub!(%r"#{beg_regex}#{list_item}#{end_regex}"i) do |match|
122
+ unless @exceptionlist.empty? then
123
+ match_start = text[start_at..-1].index(%r"#{beg_regex}#{list_item}#{end_regex}"i) + start_at
124
+ match_end = match_start + match.size-1
125
+ end
126
+ unless @exceptionlist.empty? or not protected_by_exceptionlist?(match_start,match_end,text,start_at) then
127
+ start_at = match_end + 1 unless @exceptionlist.empty?
128
+ match
129
+ else
130
+ start_at = match_end + 1 unless @exceptionlist.empty?
131
+ replace(match)
132
+ end
133
+ end
134
+ end
135
+ text
136
+ end
137
+
138
+ private
139
+
140
+ # VALIDATIONS
141
+
142
+ def validate_list_content(content)
143
+ case content
144
+ when Array then content.all? {|c| c.class == String} || raise(LanguageFilter::EmptyContentList.new("List content array is empty."))
145
+ when String then File.exists?(content) || raise(LanguageFilter::UnkownContentFile.new("List content file \"#{content}\" can't be found."))
146
+ when Pathname then content.exist? || raise(LanguageFilter::UnkownContentFile.new("List content file \"#{content}\" can't be found."))
147
+ when Symbol then
148
+ case content
149
+ when :default, :hate, :profanity, :sex, :violence then true
150
+ else raise(LanguageFilter::UnkownContent.new("The only accepted symbols are :default, :hate, :profanity, :sex, and :violence."))
151
+ end
152
+ else raise LanguageFilter::UnkownContent.new("The list content can be either an Array, Pathname, or String path to a file.")
153
+ end
154
+ end
155
+
156
+ def validate_replacement
157
+ case @replacement
158
+ when :default, :garbled, :vowels, :stars, :nonconsonants
159
+ else raise LanguageFilter::UnknownReplacement.new("This is not a known replacement type.")
160
+ end
161
+ end
162
+
163
+ # HELPERS
164
+
165
+ def set_list_content(list,options={})
166
+ case list
167
+ when :hate then load_list File.dirname(__FILE__) + "/../config/#{options[:folder] || "matchlists"}/hate.txt"
168
+ when :profanity then load_list File.dirname(__FILE__) + "/../config/#{options[:folder] || "matchlists"}/profanity.txt"
169
+ when :sex then load_list File.dirname(__FILE__) + "/../config/#{options[:folder] || "matchlists"}/sex.txt"
170
+ when :violence then load_list File.dirname(__FILE__) + "/../config/#{options[:folder] || "matchlists"}/violence.txt"
171
+ when Array then list.map {|list_item| list_item.gsub(/(?<=[^\\]|\A)\((?=[^(\?\:)])/,'(?:')}
172
+ when String, Pathname then load_list list.to_s
173
+ else []
174
+ end
175
+ end
176
+
177
+ def load_list(filepath)
178
+ IO.readlines(filepath).each {|line| line.gsub!(/\n/,''); line.gsub!(/(?<=[^\\]|\A)\((?=[^(\?\:)])/,'(?:')}
179
+ end
180
+
181
+ def use_creative_letters(text)
182
+ new_text = ""
183
+ last_char = ""
184
+ first_char_done = false
185
+ text.each_char do |char|
186
+ if last_char != '\\'
187
+ # new_text += '[\\-_\\s\\*\\.\\,\\`\\:\\\']*' if last_char != "" and char =~ /[A-Za-z]/ and first_char_done
188
+ new_text += case char.downcase
189
+ when 'a' then first_char_done = true; '(?:(?:a|@|4|\\^|/\\\\|/\\-\\\\|aye?)+)'
190
+ when 'b' then first_char_done = true; '(?:(?:b|i3|l3|13|\\|3|/3|\\\\3|3|8|6|\\u00df|p\\>|\\|\\:|[^a-z]bee+[^a-z])+)'
191
+ when 'c','k' then first_char_done = true; '(?:(?:c|\\u00a9|\\u00a2|\\(|\\[|[^a-z]cee+[^a-z]|[^a-z]see+[^a-z]|k|x|[\\|\\[\\]\\)\\(li1\\!\\u00a1][\\<\\{\\(]|[^a-z][ck]ay+[^a-z])+)'
192
+ when 'd' then first_char_done = true; '(?:(?:d|\\)|\\|\\)|\\[\\)|\\?|\\|\\>|\\|o|[^a-z]dee+[^a-z])+)'
193
+ when 'e' then first_char_done = true; '(?:(?:e|3|\\&|\\u20ac|\\u00eb|\\[\\-)+)'
194
+ when 'f' then first_char_done = true; '(?:(?:f|ph|\\u0192|[\\|\\}\\{\\\\/\\(\\)\\[\\]1il\\!][\\=\\#]|[^a-z]ef+[^a-z])+)'
195
+ when 'g' then first_char_done = true; '(?:(?:g|6|9|\\&|c\\-|\\(_\\+|[^a-z]gee+[^a-z])+)'
196
+ when 'h' then first_char_done = true; '(?:(?:h|\\#|[\\|\\}\\{\\\\/\\(\\)\\[\\]]\\-?[\\|\\}\\{\\\\/\\(\\)\\[\\]])+)'
197
+ when 'i','l' then first_char_done = true; '(?:(?:i|l|1|\\!|\\u00a1|\\||\\]|\\[|\\\\|/|[^a-z]eye[^a-z]|\\u00a3|[\\|li1\\!\\u00a1\\[\\]\\(\\)\\{\\}]_|\\u00ac|[^a-z]el+[^a-z]))'
198
+ when 'j' then first_char_done = true; '(?:(?:j|\\]|\\u00bf|_\\||_/|\\</|\\(/|[^a-z]jay+[^a-z])+)'
199
+ when 'm' then first_char_done = true; '(?:(?:m|[\\|\\(\\)/](?:\\\\/|v|\\|)[\\|\\(\\)\\\\]|\\^\\^|[^a-z]em+[^a-z])+)'
200
+ when 'n' then first_char_done = true; '(?:(?:n|[\\|/\\[\\]\\<\\>]\\\\[\\|/\\[\\]\\<\\>]|/v|\\^/|[^a-z]en+[^a-z])+)'
201
+ when 'o' then first_char_done = true; '(?:(?:o|0|\\(\\)|\\[\\]|\\u00b0|[^a-z]oh+[^a-z])+)'
202
+ when 'p' then first_char_done = true; '(?:(?:p|\\u00b6|[\\|li1\\[\\]\\!\\u00a1/\\\\][\\*o\\u00b0\\"\\>7\\^]|[^a-z]pee+[^a-z])+)'
203
+ when 'q' then first_char_done = true; '(?:(?:q|9|(?:0|\\(\\)|\\[\\])_|\\(_\\,\\)|\\<\\||[^a-z][ck]ue*|qu?eue*[^a-z])+)'
204
+ when 'r' then first_char_done = true; '(?:(?:r|[/1\\|li]?[2\\^\\?z]|\\u00ae|[^a-z]ar+[^a-z])+)'
205
+ when 's','z' then first_char_done = true; '(?:(?:s|\\$|5|\\u00a7|[^a-z]es+[^a-z]|z|2|7_|\\~/_|\\>_|\\%|[^a-z]zee+[^a-z])+)'
206
+ when 't' then first_char_done = true; '(?:(?:t|7|\\+|\\u2020|\\-\\|\\-|\\\'\\]\\[\\\')+)'
207
+ when 'u','v' then first_char_done = true; '(?:(?:u|v|\\u00b5|[\\|\\(\\)\\[\\]\\{\\}]_[\\|\\(\\)\\[\\]\\{\\}]|\\L\\||\\/|[^a-z]you[^a-z]|[^a-z]yoo+[^a-z]|[^a-z]vee+[^a-z]))'
208
+ when 'w' then first_char_done = true; '(?:(?:w|vv|\\\\/\\\\/|\\\\\\|/|\\\\\\\\\\\'|\\\'//|\\\\\\^/|\\(n\\)|[^a-z]do?u+b+l+e*[^a-z]?(?:u+|you|yoo+)[^a-z])+)'
209
+ when 'x' then first_char_done = true; '(?:(?:x|\\>\\<|\\%|\\*|\\}\\{|\\)\\(|[^a-z]e[ck]+s+[^a-z]|[^a-z]ex+[^a-z])+)'
210
+ when 'y' then first_char_done = true; '(?:(?:y|\\u00a5|j|\\\'/|[^a-z]wh?(?:y+|ie+)[^a-z])+)'
211
+ else char
212
+ end
213
+ elsif char.downcase == 'w' then
214
+ new_text += 'S'
215
+ else
216
+ new_text += char
217
+ end
218
+ last_char = char
219
+ end
220
+ new_text
221
+ end
222
+
223
+ def protected_by_exceptionlist?(match_start,match_end,text,start_at)
224
+ @exceptionlist.each do |list_item|
225
+ current_start_at = start_at
226
+ done_searching = false
227
+ until done_searching do
228
+ # puts "#{current_start_at}"
229
+ text_snippet = text[current_start_at..-1]
230
+ exception_start = text_snippet.index(%r"\b#{list_item}\b"i)
231
+ # puts "#{text_snippet[%r`\b#{list_item}\b`i]}, #{text[match_start..match_end]} :: #{current_start_at}, #{text.size} :: #{match_start}, #{match_end}" if text[match_start..match_end] == "XIII"
232
+ if exception_start then
233
+ exception_start += current_start_at
234
+ # puts "#{text_snippet[%r`\b#{list_item}\b`i]}, #{text[match_start..match_end]} :: #{current_start_at}, #{text.size} :: #{match_start}, #{match_end} :: #{exception_start}, #{text[exception_start,20]}" if text[match_start..match_end] == "XIII"
235
+ if exception_start <= match_start then
236
+ exception_end = exception_start + text_snippet[%r"\b#{list_item}\b"i].size-1
237
+ # puts "#{text_snippet[%r`\b#{list_item}\b`i]}, #{text[match_start..match_end]} :: #{current_start_at}, #{text.size} :: #{match_start}, #{match_end} :: #{exception_start}, #{exception_end}"
238
+ if exception_end >= match_end
239
+ return true
240
+ elsif text[exception_end+1..-1].index(%r"\b#{list_item}\b"i)
241
+ current_start_at = exception_end+1
242
+ else
243
+ done_searching = true
244
+ end
245
+ else
246
+ done_searching = true
247
+ end
248
+ else
249
+ done_searching = true
250
+ end
251
+ # puts text[exception_end+1..-1].index(%r"\b#{list_item}\b"i).inspect
252
+ end
253
+ end
254
+ return false
255
+ end
256
+
257
+ # This was moved to private because users should just use sanitize for any content
258
+ def replace(word)
259
+ case @replacement
260
+ when :vowels then word.gsub(/[aeiou]/i, '*')
261
+ when :stars then '*' * word.size
262
+ when :nonconsonants then word.gsub(/[^bcdfghjklmnpqrstvwxyz]/i, '*')
263
+ when :default, :garbled then '$@!#%'
264
+ else raise LanguageFilter::UnknownReplacement.new("#{@replacement} is not a known replacement type.")
265
+ end
266
+ end
267
+
268
+ def beg_regex
269
+ if @creative_letters then
270
+ CREATIVE_BEG_REGEX
271
+ else
272
+ '\\b'
273
+ end
274
+ end
275
+
276
+ def end_regex
277
+ if @creative_letters then
278
+ CREATIVE_END_REGEX
279
+ else
280
+ '\\b'
281
+ end
282
+ end
283
+ end
172
284
  end