]> git.openstreetmap.org Git - rails.git/blob - lib/rich_text.rb
Merge pull request #3414 from tomhughes/rails7
[rails.git] / lib / rich_text.rb
1 module RichText
2   SPAMMY_PHRASES = [
3     "Business Description:", "Additional Keywords:"
4   ].freeze
5
6   def self.new(format, text)
7     case format
8     when "html" then HTML.new(text || "")
9     when "markdown" then Markdown.new(text || "")
10     when "text" then Text.new(text || "")
11     end
12   end
13
14   class SimpleFormat
15     include ActionView::Helpers::TextHelper
16     include ActionView::Helpers::OutputSafetyHelper
17
18     def sanitize(text)
19       Sanitize.clean(text, Sanitize::Config::OSM).html_safe
20     end
21   end
22
23   class Base < String
24     include ActionView::Helpers::TagHelper
25
26     def spam_score
27       link_count = 0
28       link_size = 0
29
30       doc = Nokogiri::HTML(to_html)
31
32       if doc.content.empty?
33         link_proportion = 0
34       else
35         doc.xpath("//a").each do |link|
36           link_count += 1
37           link_size += link.content.length
38         end
39
40         link_proportion = link_size.to_f / doc.content.length
41       end
42
43       spammy_phrases = SPAMMY_PHRASES.count do |phrase|
44         doc.content.include?(phrase)
45       end
46
47       [link_proportion - 0.2, 0.0].max * 200 +
48         link_count * 40 +
49         spammy_phrases * 40
50     end
51
52     protected
53
54     def simple_format(text)
55       SimpleFormat.new.simple_format(text)
56     end
57
58     def sanitize(text)
59       Sanitize.clean(text, Sanitize::Config::OSM).html_safe
60     end
61
62     def linkify(text, mode = :urls)
63       if text.html_safe?
64         Rinku.auto_link(text, mode, tag_builder.tag_options(:rel => "nofollow noopener noreferrer")).html_safe
65       else
66         Rinku.auto_link(text, mode, tag_builder.tag_options(:rel => "nofollow noopener noreferrer"))
67       end
68     end
69   end
70
71   class HTML < Base
72     def to_html
73       linkify(sanitize(simple_format(self)))
74     end
75
76     def to_text
77       to_s
78     end
79   end
80
81   class Markdown < Base
82     def to_html
83       linkify(sanitize(Kramdown::Document.new(self).to_html), :all)
84     end
85
86     def to_text
87       to_s
88     end
89   end
90
91   class Text < Base
92     def to_html
93       linkify(simple_format(ERB::Util.html_escape(self)))
94     end
95
96     def to_text
97       to_s
98     end
99   end
100 end