Make system tests run by default
[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.to_f
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 linkify(text)
59       if text.html_safe?
60         Rinku.auto_link(text, :urls, tag_builder.tag_options(:rel => "nofollow")).html_safe
61       else
62         Rinku.auto_link(text, :urls, tag_builder.tag_options(:rel => "nofollow"))
63       end
64     end
65   end
66
67   class HTML < Base
68     def to_html
69       linkify(sanitize(simple_format(self)))
70     end
71
72     def to_text
73       to_s
74     end
75
76     private
77
78     def sanitize(text)
79       Sanitize.clean(text, Sanitize::Config::OSM).html_safe
80     end
81   end
82
83   class Markdown < Base
84     def to_html
85       Markdown.html_parser.render(self).html_safe
86     end
87
88     def to_text
89       to_s
90     end
91
92     def self.html_renderer
93       @html_renderer ||= Redcarpet::Render::XHTML.new(:filter_html => true, :safe_links_only => true, :link_attributes => { :rel => "nofollow" })
94     end
95
96     def self.html_parser
97       @html_parser ||= Redcarpet::Markdown.new(html_renderer, :no_intra_emphasis => true, :autolink => true, :space_after_headers => true)
98     end
99   end
100
101   class Text < Base
102     def to_html
103       linkify(simple_format(ERB::Util.html_escape(self)))
104     end
105
106     def to_text
107       to_s
108     end
109   end
110 end