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