html_truncator 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/README.md +19 -8
  2. data/lib/html_truncator.rb +32 -17
  3. metadata +3 -3
data/README.md CHANGED
@@ -14,19 +14,19 @@ It's very simple. Install it with rubygems:
14
14
 
15
15
  Or, if you use bundler, add it to your `Gemfile`:
16
16
 
17
- gem "html_truncator", :version => "~>0.1"
17
+ gem "html_truncator", :version => "~>0.2"
18
18
 
19
19
  Then you can use it in your code:
20
20
 
21
21
  require "html_truncator"
22
22
  HTML_Truncator.truncate("<p>Lorem ipsum dolor sit amet.</p>", 3)
23
- # => "<p>Lorem ipsum dolor...</p>"
23
+ # => "<p>Lorem ipsum dolor…</p>"
24
24
 
25
25
  The HTML_Truncator class has only one method, `truncate`, with 3 arguments:
26
26
 
27
27
  * the HTML-formatted string to truncate
28
28
  * the number of words to keep (real words, tags and attributes aren't count)
29
- * the ellipsis (optional, '...' by default).
29
+ * some options like the ellipsis (optional, '' by default).
30
30
 
31
31
  And an attribute, `ellipsable_tags`, which lists the tags that can contain the ellipsis
32
32
  (by default: p ol ul li div header article nav section footer aside dd dt dl).
@@ -38,33 +38,43 @@ Examples
38
38
  A simple example:
39
39
 
40
40
  HTML_Truncator.truncate("<p>Lorem ipsum dolor sit amet.</p>", 3)
41
- # => "<p>Lorem ipsum dolor...</p>"
41
+ # => "<p>Lorem ipsum dolor…</p>"
42
42
 
43
43
  If the text is too short to be truncated, it won't be modified:
44
44
 
45
45
  HTML_Truncator.truncate("<p>Lorem ipsum dolor sit amet.</p>", 5)
46
46
  # => "<p>Lorem ipsum dolor sit amet.</p>"
47
47
 
48
+ If you prefer, you can have the length in characters instead of words:
49
+
50
+ HTML_Truncator.truncate("<p>Lorem ipsum dolor sit amet.</p>", 12, :length_in_chars => true)
51
+ # => "<p>Lorem ipsum …</p>"
52
+
48
53
  You can customize the ellipsis:
49
54
 
50
- HTML_Truncator.truncate("<p>Lorem ipsum dolor sit amet.</p>", 3, " (truncated)")
55
+ HTML_Truncator.truncate("<p>Lorem ipsum dolor sit amet.</p>", 3, :ellipsis => " (truncated)")
51
56
  # => "<p>Lorem ipsum dolor (truncated)</p>"
52
57
 
53
58
  And even have HTML in the ellipsis:
54
59
 
55
- HTML_Truncator.truncate("<p>Lorem ipsum dolor sit amet.</p>", 3, '<a href="/more-to-read">...</a>')
60
+ HTML_Truncator.truncate("<p>Lorem ipsum dolor sit amet.</p>", 3, :ellipsis => '<a href="/more-to-read">...</a>')
56
61
  # => "<p>Lorem ipsum dolor<a href="/more-to-read">...</a></p>"
57
62
 
58
63
  The ellipsis is put at the right place, inside `<p>`, but not `<i>`:
59
64
 
60
65
  HTML_Truncator.truncate("<p><i>Lorem ipsum dolor sit amet.</i></p>", 3)
61
- # => "<p><i>Lorem ipsum dolor</i>...</p>"
66
+ # => "<p><i>Lorem ipsum dolor</i>…</p>"
62
67
 
63
68
  You can indicate that a tag can contain the ellipsis but adding it to the ellipsable_tags:
64
69
 
65
70
  HTML_Truncator.ellipsable_tags << "blockquote"
66
71
  HTML_Truncator.truncate("<blockquote>Lorem ipsum dolor sit amet.</blockquote>", 3)
67
- # => "<blockquote>Lorem ipsum dolor...</blockquote>"
72
+ # => "<blockquote>Lorem ipsum dolor…</blockquote>"
73
+
74
+ You can know if a string was truncated with the `html_truncated?` method:
75
+
76
+ HTML_Truncator.truncate("<p>Lorem ipsum dolor sit amet.</p>", 3).html_truncated?
77
+ # => true
68
78
 
69
79
 
70
80
  Alternatives
@@ -102,5 +112,6 @@ Credits
102
112
  -------
103
113
 
104
114
  Thanks to François de Metz for his awesome help!
115
+ Thanks to [kuroir](https://github.com/kuroir) and [benhutton](https://github.com/benhutton) for their suggestions.
105
116
 
106
117
  Copyright (c) 2011 Bruno Michel <bmichel@menfin.info>, released under the MIT license
@@ -1,11 +1,19 @@
1
+ # encoding: utf-8
2
+
1
3
  require "nokogiri"
2
4
  require "set"
3
5
 
4
6
 
5
7
  class HTML_Truncator
6
- def self.truncate(text, max_words, ellipsis="...")
8
+ DEFAULT_OPTIONS = { :ellipsis => "", :length_in_chars => false }
9
+
10
+ def self.truncate(text, max, opts={})
11
+ return truncate(text, max, :ellipsis => opts) if String === opts
12
+ opts = DEFAULT_OPTIONS.merge(opts)
7
13
  doc = Nokogiri::HTML::DocumentFragment.parse(text)
8
- doc.truncate(max_words, ellipsis).first
14
+ str, _, opts = doc.truncate(max, opts)
15
+ eval "class <<str; def html_truncated?; #{opts[:was_truncated]} end end"
16
+ str
9
17
  end
10
18
 
11
19
  class <<self
@@ -22,28 +30,29 @@ class Nokogiri::HTML::DocumentFragment
22
30
  end
23
31
 
24
32
  class Nokogiri::XML::Node
25
- def truncate(max_words, ellipsis)
26
- return ["", 1, ellipsis] if max_words == 0 && !ellipsable?
27
- inner, remaining, ellipsis = inner_truncate(max_words, ellipsis)
33
+ def truncate(max, opts)
34
+ return ["", 1, opts] if max == 0 && !ellipsable?
35
+ inner, remaining, opts = inner_truncate(max, opts)
28
36
  children.remove
29
37
  add_child Nokogiri::HTML::DocumentFragment.parse(inner)
30
- [to_xml(:indent => 0), max_words - remaining, ellipsis]
38
+ [to_html(:indent => 0), max - remaining, opts]
31
39
  end
32
40
 
33
- def inner_truncate(max_words, ellipsis)
34
- inner, remaining = "", max_words
41
+ def inner_truncate(max, opts)
42
+ inner, remaining = "", max
35
43
  self.children.each do |node|
36
- txt, nb, ellipsis = node.truncate(remaining, ellipsis)
44
+ txt, nb, opts = node.truncate(remaining, opts)
37
45
  remaining -= nb
38
46
  inner += txt
39
47
  next if remaining >= 0
40
48
  if ellipsable?
41
- inner += ellipsis
42
- ellipsis = ""
49
+ inner += opts[:ellipsis]
50
+ opts[:ellipsis] = ""
51
+ opts[:was_truncated] = true
43
52
  end
44
53
  break
45
54
  end
46
- [inner, remaining, ellipsis]
55
+ [inner, remaining, opts]
47
56
  end
48
57
 
49
58
  def ellipsable?
@@ -52,10 +61,16 @@ class Nokogiri::XML::Node
52
61
  end
53
62
 
54
63
  class Nokogiri::XML::Text
55
- def truncate(max_words, ellipsis)
56
- words = content.split
57
- nb_words = words.length
58
- return [to_xhtml, nb_words, ellipsis] if nb_words <= max_words && max_words > 0
59
- [words.slice(0, max_words).join(' '), nb_words, ellipsis]
64
+ def truncate(max, opts)
65
+ if opts[:length_in_chars]
66
+ count = content.length
67
+ return [to_xhtml, count, opts] if count <= max && max > 0
68
+ [content.slice(0, max), count, opts]
69
+ else
70
+ words = content.split
71
+ count = words.length
72
+ return [to_xhtml, count, opts] if count <= max && max > 0
73
+ [words.slice(0, max).join(' '), count, opts]
74
+ end
60
75
  end
61
76
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
8
7
  - 2
9
- version: 0.1.2
8
+ - 0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Bruno Michel
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-14 00:00:00 +01:00
17
+ date: 2011-01-28 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency