nokogiri_truncate_html 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,66 @@
1
+ require 'nokogiri'
2
+ require 'cgi'
3
+
4
+ module NokogiriTruncateHtml
5
+ class TruncateFinished < Exception
6
+ end
7
+
8
+ class TruncateDocument < Nokogiri::XML::SAX::Document
9
+
10
+ def initialize
11
+ # We use the xhtml "flavour" so that we can decode
12
+ # apostrophes. That is the only difference between
13
+ # xhtml1 and html4.
14
+ @encoder = HTMLEntities.new('xhtml1')
15
+ @discard_first_element = false
16
+ end
17
+
18
+ def length=(length)
19
+ @length = length
20
+ end
21
+
22
+ def omission=(omission)
23
+ @omission = omission
24
+ end
25
+
26
+ def output
27
+ while @tags.size > 0
28
+ @output << "</#{@tags.pop}>"
29
+ end
30
+ @output
31
+ end
32
+
33
+ def start_document
34
+ @output, @chars_remaining, @tags = '', @length, []
35
+ @discard_first_element = false
36
+ end
37
+
38
+ def characters(string)
39
+ text = @encoder.decode(string)
40
+ @output << CGI.escapeHTML(text[0, @chars_remaining])
41
+ @chars_remaining -= text.length
42
+ if @chars_remaining < 0
43
+ @output << @omission
44
+ raise TruncateFinished
45
+ end
46
+ end
47
+
48
+ def start_element(name, attrs = [])
49
+ unless @discard_first_element
50
+ return if %w(html body).include? name
51
+ return @discard_first_element = true
52
+ end
53
+
54
+ if %w(br embed hr img input param).include? name
55
+ @output << "<#{name}#{' ' if attrs.size > 0 }#{attrs.map { |attr,val| "#{attr}=\"#{val}\"" }.join(' ')} />"
56
+ else
57
+ @output << "<#{name}#{' ' if attrs.size > 0 }#{attrs.map { |attr,val| "#{attr}=\"#{val}\"" }.join(' ')}>"
58
+ @tags.push name
59
+ end
60
+ end
61
+
62
+ def end_element(name)
63
+ @output << "</#{@tags.pop}>" if @tags.last == name
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,37 @@
1
+ require 'active_support/core_ext/module/attribute_accessors.rb'
2
+ require 'active_support/core_ext/string/output_safety'
3
+ require 'nokogiri_truncate_html/truncate_document'
4
+
5
+ module NokogiriTruncateHtml
6
+ module TruncateHtmlHelper
7
+ mattr_accessor :parser
8
+ mattr_accessor :document
9
+
10
+ # Truncates html respecting tags and html entities.
11
+ #
12
+ # The API is the same as ActionView::Helpers::TextHelper#truncate. It uses Nokogiri and HtmlEntities for entity awareness.
13
+ #
14
+ # Examples:
15
+ # truncate_html '<p>Hello <strong>World</strong></p>', :length => 7 # => '<p>Hello <strong>W&hellip;</strong></p>'
16
+ # truncate_html '<p>Hello &amp; Goodbye</p>', :length => 7 # => '<p>Hello &amp;&hellip;</p>'
17
+ def truncate_html(input, *args)
18
+ self.document ||= TruncateDocument.new#(TruncateHtmlHelper.flavor) #, length, omission)
19
+ self.parser ||= Nokogiri::HTML::SAX::Parser.new(document)
20
+
21
+ # support both 2.2 & earlier APIs
22
+ options = args.extract_options!
23
+ length = options[:length] || args[0] || 30
24
+ omission = options[:omission] || args[1] || '&hellip;'
25
+
26
+ # Adding div around the input is a hack. It gets removed in TruncateDocument.
27
+ input = "<div>#{input}</div>"
28
+ self.document.length = length
29
+ self.document.omission = omission
30
+ begin
31
+ self.parser.parse_memory(input)
32
+ rescue TruncateFinished
33
+ end
34
+ self.document.output.html_safe
35
+ end
36
+ end
37
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nokogiri_truncate_html
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -83,6 +83,8 @@ executables: []
83
83
  extensions: []
84
84
  extra_rdoc_files: []
85
85
  files:
86
+ - lib/nokogiri_truncate_html/truncate_html_helper.rb
87
+ - lib/nokogiri_truncate_html/truncate_document.rb
86
88
  - lib/nokogiri_truncate_html.rb
87
89
  homepage: https://github.com/Springest/truncate_html
88
90
  licenses: []