discourse/lib/text_sentinel.rb

60 lines
1.6 KiB
Ruby
Raw Normal View History

#
# Given a string, tell us whether or not is acceptable. Also, remove stuff we don't like
# such as leading / trailing space.
#
class TextSentinel
attr_accessor :text
def self.non_symbols_regexp
/[\ -\/\[-\`\:-\@\{-\~]/m
end
def initialize(text, opts=nil)
@opts = opts || {}
2013-02-16 05:36:19 +08:00
if text.present?
@text = text.encode('UTF-8', invalid: :replace, undef: :replace, replace: '')
@text.gsub!(/ +/m, ' ') if @opts[:remove_interior_spaces]
@text.strip! if @opts[:strip]
end
end
2013-02-09 05:55:40 +08:00
def self.title_sentinel(text)
2013-02-26 00:42:20 +08:00
TextSentinel.new(text,
2013-02-09 05:55:40 +08:00
min_entropy: SiteSetting.title_min_entropy,
max_word_length: SiteSetting.max_word_length,
remove_interior_spaces: true,
strip: true)
2013-02-09 05:55:40 +08:00
end
2013-02-26 00:42:20 +08:00
# Entropy is a number of how many unique characters the string needs.
def entropy
return 0 if @text.blank?
@entropy ||= @text.strip.each_char.to_a.uniq.size
end
2013-02-26 00:42:20 +08:00
def valid?
# Blank strings are not valid
return false if @text.blank? || @text.strip.blank?
# Entropy check if required
return false if @opts[:min_entropy].present? && (entropy < @opts[:min_entropy])
# We don't have a comprehensive list of symbols, but this will eliminate some noise
non_symbols = @text.gsub(TextSentinel.non_symbols_regexp, '').size
return false if non_symbols == 0
# Don't allow super long strings without spaces
return false if @opts[:max_word_length] && @text =~ /\w{#{@opts[:max_word_length]},}(\s|$)/
# We don't allow all upper case content in english
return false if (@text =~ /[A-Z]+/) && (@text == @text.upcase)
true
end
end