Cleanup trailing whitespace
[rails.git] / lib / rich_text.rb
1 module RichText
2   def self.new(format, text)
3     case format
4     when "html"; HTML.new(text || "")
5     when "markdown"; Markdown.new(text || "")
6     when "text"; Text.new(text || "")
7     else; nil
8     end
9   end
10
11   class SimpleFormat
12     include ActionView::Helpers::TextHelper
13     include ActionView::Helpers::OutputSafetyHelper
14
15     def sanitize(text)
16       Sanitize.clean(text, Sanitize::Config::OSM).html_safe
17     end
18   end
19
20   class Base < String
21     include ActionView::Helpers::TagHelper
22
23     def spam_score
24       link_count = 0
25       link_size = 0
26
27       doc = Nokogiri::HTML(to_html)
28
29       if doc.content.length > 0
30         doc.xpath("//a").each do |link|
31           link_count += 1
32           link_size += link.content.length
33         end
34
35         link_proportion = link_size.to_f / doc.content.length.to_f
36       else
37         link_proportion = 0
38       end
39
40       return [link_proportion - 0.2, 0.0].max * 200 + link_count * 40
41     end
42
43   protected
44
45     def simple_format(text)
46       SimpleFormat.new.simple_format(text)
47     end
48
49     def linkify(text)
50       if text.html_safe?
51         Rinku.auto_link(text, :urls, tag_options(:rel => "nofollow")).html_safe
52       else
53         Rinku.auto_link(text, :urls, tag_options(:rel => "nofollow"))
54       end
55     end
56   end
57
58   class HTML < Base
59     def to_html
60       linkify(sanitize(simple_format(self)))
61     end
62
63     def to_text
64       self.to_s
65     end
66
67   private
68
69     def sanitize(text)
70       Sanitize.clean(text, Sanitize::Config::OSM).html_safe
71     end
72   end
73
74   class Markdown < Base
75     def to_html
76       html_parser.render(self).html_safe
77     end
78
79     def to_text
80       self.to_s
81     end
82
83   private
84
85     def html_parser
86       @@html_renderer ||= Renderer.new({
87         :filter_html => true, :safe_links_only => true
88       })
89       @@html_parser ||= Redcarpet::Markdown.new(@@html_renderer, {
90         :no_intra_emphasis => true, :autolink => true, :space_after_headers => true
91       })
92     end
93
94     class Renderer < Redcarpet::Render::XHTML
95       def link(link, title, alt_text)
96         "<a rel=\"nofollow\" href=\"#{link}\">#{alt_text}</a>"
97       end
98
99       def autolink(link, link_type)
100         if link_type == :email
101           "<a rel=\"nofollow\" href=\"mailto:#{link}\">#{link}</a>"
102         else
103           "<a rel=\"nofollow\" href=\"#{link}\">#{link}</a>"
104         end
105       end
106     end
107   end
108
109   class Text < Base
110     def to_html
111       linkify(simple_format(ERB::Util.html_escape(self)))
112     end
113
114     def to_text
115       self.to_s
116     end
117   end
118 end