Link to the Markdown spec
[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     else; nil
7     end
8   end
9
10   class Base < String
11     def spam_score
12       link_count = 0
13       link_size = 0
14
15       doc = Nokogiri::HTML(to_html)
16
17       if doc.content.length > 0
18         doc.xpath("//a").each do |link|
19           link_count += 1
20           link_size += link.content.length
21         end
22
23         link_proportion = link_size.to_f / doc.content.length.to_f
24       else
25         link_proportion = 0
26       end
27
28       return [link_proportion - 0.2, 0.0].max * 200 + link_count * 20
29     end
30   end
31
32   class HTML < Base
33     include ActionView::Helpers::TextHelper
34     include ActionView::Helpers::TagHelper
35
36     def to_html
37       linkify(sanitize(simple_format(self)))
38     end
39
40     def to_text
41       self
42     end
43
44   private
45
46     def sanitize(text)
47       Sanitize.clean(text, Sanitize::Config::OSM).html_safe
48     end
49
50     def linkify(text)
51       if text.html_safe?
52         Rinku.auto_link(text, :urls, tag_options(:rel => "nofollow")).html_safe
53       else
54         Rinku.auto_link(text, :urls, tag_options(:rel => "nofollow"))
55       end
56     end
57   end
58
59   class Markdown < Base
60     def to_html
61       html_parser.render(self).html_safe
62     end
63
64     def to_text
65       self
66     end
67
68   private
69
70     def html_parser
71       @@html_renderer ||= Redcarpet::Render::XHTML.new({
72         :filter_html => true, :safe_links_only => true
73       })
74       @@html_parser ||= Redcarpet::Markdown.new(@@html_renderer, {
75         :no_intra_emphasis => true, :autolink => true, :space_after_headers => true
76       })
77     end
78   end
79 end