forked from discourse/discourse
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexcerpt_parser.rb
84 lines (73 loc) · 2.2 KB
/
excerpt_parser.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
class ExcerptParser < Nokogiri::XML::SAX::Document
attr_reader :excerpt
def initialize(length, options=nil)
@length = length
@excerpt = ""
@current_length = 0
options || {}
@strip_links = options[:strip_links] == true
@text_entities = options[:text_entities] == true
@markdown_images = options[:markdown_images] == true
end
def self.get_excerpt(html, length, options)
me = self.new(length,options)
parser = Nokogiri::HTML::SAX::Parser.new(me)
catch(:done) do
parser.parse(html) unless html.nil?
end
me.excerpt.strip!
me.excerpt
end
def include_tag(name, attributes)
characters("<#{name} #{attributes.map{|k,v| "#{k}='#{v}'"}.join(' ')}>", false, false, false)
end
def start_element(name, attributes=[])
case name
when "img"
# If include_images is set, include the image in markdown
characters("!") if @markdown_images
attributes = Hash[*attributes.flatten]
if attributes["alt"]
characters("[#{attributes["alt"]}]")
elsif attributes["title"]
characters("[#{attributes["title"]}]")
else
characters("[image]")
end
characters("(#{attributes['src']})") if @markdown_images
when "a"
unless @strip_links
include_tag(name, attributes)
@in_a = true
end
when "aside"
@in_quote = true
end
end
def end_element(name)
case name
when "a"
unless @strip_links
characters("</a>",false, false, false)
@in_a = false
end
when "p", "br"
characters(" ")
when "aside"
@in_quote = false
end
end
def characters(string, truncate = true, count_it = true, encode = true)
return if @in_quote
encode = encode ? lambda{|s| ERB::Util.html_escape(s)} : lambda {|s| s}
if count_it && @current_length + string.length > @length
length = [0, @length - @current_length - 1].max
@excerpt << encode.call(string[0..length]) if truncate
@excerpt << (@text_entities ? "..." : "…")
@excerpt << "</a>" if @in_a
throw :done
end
@excerpt << encode.call(string)
@current_length += string.length if count_it
end
end