truncate_html 0.5.5 → 0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,4 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
4
3
  - 1.9.2
5
4
  - jruby-19mode # JRuby in 1.9 mode
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- truncate_html (0.5.5)
4
+ truncate_html (0.9)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -1,7 +1,8 @@
1
1
  TruncateHtml
2
2
  ============
3
3
 
4
- [![Build Status](https://secure.travis-ci.org/hgimenez/truncate_html.png?branch=master)](http://travis-ci.org/hgimenez/truncate_html)
4
+ [![Build Status](https://secure.travis-ci.org/hgmnz/truncate_html.png?branch=master)](http://travis-ci.org/hgmnz/truncate_html)
5
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/hgmnz/truncate_html)
5
6
 
6
7
  truncate_html is a Rails helper plugin that [cuts off](http://www.youtube.com/watch?v=6XG4DIOA7nU) a string of HTML and takes care of closing any lingering open tags. There are many possible solutions to this. This plugin does not have any dependencies, and does all it's work via [regular expressions](http://xkcd.com/208/).
7
8
 
@@ -11,9 +12,11 @@ The API is very similar to Rails' own <code>truncate()</code> method.
11
12
  Example
12
13
  -------
13
14
 
14
- some_html = '<ul><li><a href="http://whatever">This is a link</a></li></ul>'
15
- truncate_html(some_html, :length => 15, :omission => '...(continued)')
16
- => <ul><li><a href="http://whatever">This...(continued)</a></li></ul>
15
+ ```ruby
16
+ some_html = '<ul><li><a href="http://whatever">This is a link</a></li></ul>'
17
+ truncate_html(some_html, :length => 15, :omission => '...(continued)')
18
+ => <ul><li><a href="http://whatever">This...(continued)</a></li></ul>
19
+ ```
17
20
 
18
21
  A few notes:
19
22
 
@@ -22,21 +25,49 @@ A few notes:
22
25
  * If the input HTML is nil, it will return an empty string.
23
26
  * The omission text's length does count toward the resulting string's length.
24
27
  * `<script>` tags will pass right through - they will not count toward the resulting string's length, or be truncated.
28
+
25
29
  * The default options are:
26
30
  * :length => 100
27
31
  * :omission => '...'
28
32
  * :word_boundary => true
29
33
 
30
34
  You may also set global configuration options.
31
- For example, place the following on a sensible place,
32
- like `config/initializers/truncate_html.rb`
33
-
34
- TruncateHtml.configure do |config|
35
- config.length = 50
36
- config.omission = '...(continued)'
37
- config.word_boundary = false
38
- end
39
-
35
+ For example, place the following on application boot,
36
+ something like `config/initializers/truncate_html.rb`
37
+
38
+ ```ruby
39
+ TruncateHtml.configure do |config|
40
+ config.length = 50
41
+ config.omission = '...(continued)'
42
+ config.word_boundary = false
43
+ config.break_token = '<!-- break -->'
44
+ end
45
+ ```
46
+
47
+ If you really want, you can even set a custom word boundary regexp.
48
+ For example, to truncate at the end of the nearest sentence:
49
+
50
+ ```ruby
51
+ TruncateHtml.configure do |config|
52
+ config.length = 50
53
+ config.omission = ''
54
+ config.word_boundary = /\S[\.\?\!]/
55
+ end
56
+ ```
57
+
58
+ You can also truncate the html at a specific point not based on length but content.
59
+ To do that, place the `:break_token` in your source. This allows the truncation to be
60
+ data driven, breaking after a leading paragraph or sentence. If the
61
+ `:break_token` is in your content before the specified :length, :length will be
62
+ ignored and the content truncated at :break_token
63
+ If the `:break_token` is in your content after the specified :length,
64
+ `:break_token` will be ignored and the content truncated at :length
65
+
66
+ ```ruby
67
+ TruncateHtml.configure do |config|
68
+ config.break_token = '<!-- truncate -->
69
+ end
70
+ ```
40
71
  Installation
41
72
  ------------
42
73
 
@@ -52,7 +83,7 @@ For Rails 3, use the latest truncate_html:
52
83
  Issues or Suggestions
53
84
  ---------------------
54
85
 
55
- Found an issue or have a suggestion? Please report it on [Github's issue tracker](http://github.com/hgimenez/truncate_html/issues).
86
+ Found an issue or have a suggestion? Please report it on [Github's issue tracker](http://github.com/hgmnz/truncate_html/issues).
56
87
 
57
88
  Testing
58
89
  -------
@@ -64,4 +95,4 @@ All green? Go hack.
64
95
 
65
96
  Copyright (c) 2009 - 2010 Harold A. Giménez, released under the MIT license
66
97
 
67
- Thanks to all the [contributors](https://github.com/hgimenez/truncate_html/contributors)!
98
+ Thanks to all the [contributors](https://github.com/hgmnz/truncate_html/contributors)!
@@ -7,7 +7,7 @@ require File.join(File.dirname(__FILE__), 'app', 'helpers', 'truncate_html_helpe
7
7
  TruncateHtml.configure do |config|
8
8
  config.length = 100
9
9
  config.omission = '...'
10
- config.word_boundary = true
10
+ config.word_boundary = /\S/
11
11
  end
12
12
 
13
13
  ActionController::Base.helper(TruncateHtmlHelper)
@@ -1,6 +1,6 @@
1
1
  module TruncateHtml
2
2
  class Configuration
3
- attr_accessor :length, :omission, :word_boundary
3
+ attr_accessor :length, :omission, :word_boundary, :break_token
4
4
  end
5
5
 
6
6
  class << self
@@ -34,8 +34,7 @@ module TruncateHtml
34
34
 
35
35
  private
36
36
  def regex
37
- punctuation = if RUBY_VERSION < '1.9' then "\\p\\{P\\}" else "[[:punct:]]" end
38
- /(?:<script.*>.*<\/script>)+|<\/?[^>]+>|[#{"[[:alpha:]]" if RUBY_VERSION >= '1.9'}\w\|`~!@#\$%^&*\(\)\-_\+=\[\]{}:;'",\.\/?]+|\s+|#{punctuation}/
37
+ /(?:<script.*>.*<\/script>)+|<\/?[^>]+>|[[[:alpha:]]\w\|`~!@#\$%^&*\(\)\-_\+=\[\]{}:;'",\.\/?]+|\s+|[[:punct:]]/
39
38
  end
40
39
 
41
40
  end
@@ -6,67 +6,79 @@ module TruncateHtml
6
6
  end
7
7
 
8
8
  def truncate(options = {})
9
- length = options[:length] || TruncateHtml.configuration.length
10
- @omission = options[:omission] || TruncateHtml.configuration.omission
11
- @word_boundary = (options.has_key?(:word_boundary) ? options[:word_boundary] : TruncateHtml.configuration.word_boundary)
9
+ length = options[:length] || TruncateHtml.configuration.length
10
+ @omission = options[:omission] || TruncateHtml.configuration.omission
11
+ @word_boundary = (options.has_key?(:word_boundary) ? options[:word_boundary] : TruncateHtml.configuration.word_boundary)
12
+ @break_token = options[:break_token] || TruncateHtml.configuration.break_token || nil
12
13
  @chars_remaining = length - @omission.length
13
14
  @open_tags, @truncated_html = [], ['']
14
15
 
15
16
  return @omission if @chars_remaining < 0
16
17
  @original_html.html_tokens.each do |token|
17
- #if truncate_more?(token)
18
- if @chars_remaining > 0
19
- process_token(token)
20
- else
18
+ if @chars_remaining <= 0 || truncate_token?(token)
21
19
  close_open_tags
22
20
  break
21
+ else
22
+ process_token(token)
23
23
  end
24
24
  end
25
- @truncated_html.join
25
+
26
+ out = @truncated_html.join
27
+
28
+ if @word_boundary
29
+ term_regexp = Regexp.new("^.*#{@word_boundary.source}")
30
+ match = out.match(term_regexp)
31
+ match ? match[0] : out
32
+ else
33
+ out
34
+ end
26
35
  end
27
36
 
28
37
  private
29
38
 
30
- def process_token(token)
31
- append_to_result(token)
32
- if token.html_tag?
33
- if token.open_tag?
34
- @open_tags << token
35
- else
36
- remove_latest_open_tag(token)
37
- end
39
+ def process_token(token)
40
+ append_to_result(token)
41
+ if token.html_tag?
42
+ if token.open_tag?
43
+ @open_tags << token
38
44
  else
39
- @chars_remaining -= (@word_boundary ? token.length : token[0, @chars_remaining].length)
40
- if @chars_remaining <= 0
41
- @truncated_html[-1] = @truncated_html[-1].rstrip + @omission
42
- end
45
+ remove_latest_open_tag(token)
46
+ end
47
+ else
48
+ @chars_remaining -= (@word_boundary ? token.length : token[0, @chars_remaining].length)
49
+ if @chars_remaining <= 0
50
+ @truncated_html[-1] = @truncated_html[-1].rstrip + @omission
43
51
  end
44
52
  end
53
+ end
45
54
 
46
- def append_to_result(token)
47
- if token.html_tag?
48
- @truncated_html << token
49
- elsif @word_boundary
50
- @truncated_html << token if (@chars_remaining - token.length) >= 0
51
- else
52
- @truncated_html << token[0, @chars_remaining]
53
- end
55
+ def append_to_result(token)
56
+ if token.html_tag?
57
+ @truncated_html << token
58
+ elsif @word_boundary
59
+ @truncated_html << token if (@chars_remaining - token.length) >= 0
60
+ else
61
+ @truncated_html << token[0, @chars_remaining]
54
62
  end
63
+ end
55
64
 
56
- def close_open_tags
57
- @open_tags.reverse_each do |open_tag|
58
- @truncated_html << open_tag.matching_close_tag
59
- end
65
+ def close_open_tags
66
+ @open_tags.reverse_each do |open_tag|
67
+ @truncated_html << open_tag.matching_close_tag
60
68
  end
69
+ end
61
70
 
62
- def remove_latest_open_tag(close_tag)
63
- (0...@open_tags.length).to_a.reverse.each do |index|
64
- if @open_tags[index].matching_close_tag == close_tag
65
- @open_tags.delete_at(index)
66
- break
67
- end
71
+ def remove_latest_open_tag(close_tag)
72
+ (0...@open_tags.length).to_a.reverse.each do |index|
73
+ if @open_tags[index].matching_close_tag == close_tag
74
+ @open_tags.delete_at(index)
75
+ break
68
76
  end
69
77
  end
78
+ end
70
79
 
80
+ def truncate_token?(token)
81
+ @break_token and token == @break_token
82
+ end
71
83
  end
72
84
  end
@@ -1,3 +1,3 @@
1
1
  module TruncateHtml
2
- VERSION = "0.5.5"
2
+ VERSION = "0.9"
3
3
  end
@@ -17,6 +17,22 @@ describe TruncateHtml::HtmlTruncator do
17
17
  html = 'some text <span class="caps">CAPS</span> some text'
18
18
  truncate(html, :length => 25, :word_boundary => false).should == 'some text <span class="caps">CAPS</span> some te...'
19
19
  end
20
+
21
+ context 'and a custom omission value is passed' do
22
+ it 'retains the omission text' do
23
+ truncate_html("testtest", :length => 10, :omission => '..', :word_boundary => false).should == 'testtest..'
24
+ end
25
+
26
+ it 'handles multibyte characters' do
27
+ truncate_html("prüfenprüfen", :length => 8, :omission => '..', :word_boundary => false). should == 'prüfen..'
28
+ end
29
+ end
30
+ end
31
+
32
+ context 'when the word_boundary option is a custom value (for splitting on sentences)' do
33
+ it 'truncates to the end of the nearest sentence' do
34
+ truncate_html('hello there. or maybe not?', :length => 16, :omission => '', :word_boundary => /\S[\.\?\!]/).should == 'hello there.'
35
+ end
20
36
  end
21
37
 
22
38
  it "includes the omission text's length in the returned truncated html" do
@@ -124,4 +140,52 @@ describe TruncateHtml::HtmlTruncator do
124
140
  result.should include "<p>“我现在使用的是中文的拼音。”<br>"
125
141
  end
126
142
 
143
+ context 'when the break_token option is set as <!-- truncate -->' do
144
+ it 'does not truncate abnormally if the break_token is not present' do
145
+ truncate('This is line one. This is line two.', :length => 30, :break_token => '<!-- truncate -->').should == 'This is line one. This is...'
146
+ end
147
+ it 'does not truncate abnormally if the break_token is present, but beyond the length param' do
148
+ truncate('This is line one. This is line <!-- truncate --> two.', :length => 30, :break_token => '<!-- truncate -->').should == 'This is line one. This is...'
149
+ end
150
+ it 'truncates before the length param if the break_token is before the token at "length"' do
151
+ truncate('This is line one. <!-- truncate --> This is line two.', :length => 30, :break_token => '<!-- truncate -->').should == 'This is line one.'
152
+ end
153
+ end
154
+
155
+ context 'when the break_token option is customized as a comment' do
156
+ it 'does not truncate abnormally if the break_token is not present' do
157
+ truncate('This is line one. This is line two.', :length => 30, :break_token => '<!-- break -->').should == 'This is line one. This is...'
158
+ end
159
+ it 'does not truncate abnormally if the break_token is present, but beyond the length param' do
160
+ truncate('This is line one. This is line <!-- break --> two.', :length => 30, :break_token => '<!-- break -->').should == 'This is line one. This is...'
161
+ end
162
+ it 'truncates before the length param if the break_token is before the token at "length"' do
163
+ truncate('This is line one. <!-- break --> This is line two.', :length => 30, :break_token => '<!-- break -->').should == 'This is line one.'
164
+ end
165
+ end
166
+
167
+ context 'when the break_token option is customized as an html tag' do
168
+ it 'does not truncate abnormally if the break_token is not present' do
169
+ truncate('This is line one. This is line two.', :length => 30, :break_token => '<break />').should == 'This is line one. This is...'
170
+ end
171
+ it 'does not truncate abnormally if the break_token is present, but beyond the length param' do
172
+ truncate('This is line one. This is line <break /> two.', :length => 30, :break_token => '<break />').should == 'This is line one. This is...'
173
+ end
174
+ it 'truncates before the length param if the break_token is before the token at "length"' do
175
+ truncate('This is line one. <break /> This is line two.', :length => 30, :break_token => '<break />').should == 'This is line one.'
176
+ end
177
+ end
178
+
179
+ context 'when the break_token option is customized as a word' do
180
+ it 'does not truncate abnormally if the break_token is not present' do
181
+ truncate('This is line one. This is line two.', :length => 30, :break_token => 'foobar').should == 'This is line one. This is...'
182
+ end
183
+ it 'does not truncate abnormally if the break_token is present, but beyond the length param' do
184
+ truncate('This is line one. This is line foobar two.', :length => 30, :break_token => 'foobar').should == 'This is line one. This is...'
185
+ end
186
+ it 'truncates before the length param if the break_token is before the token at "length"' do
187
+ truncate('This is line one. foobar This is line two.', :length => 30, :break_token => 'foobar').should == 'This is line one.'
188
+ end
189
+ end
190
+
127
191
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: truncate_html
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.5
4
+ version: '0.9'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-24 00:00:00.000000000 Z
12
+ date: 2013-01-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec-rails
16
- requirement: &70108244979240 !ruby/object:Gem::Requirement
16
+ requirement: &70117859351640 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '2.9'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70108244979240
24
+ version_requirements: *70117859351640
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rails
27
- requirement: &70108244978720 !ruby/object:Gem::Requirement
27
+ requirement: &70117859350560 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: 3.0.3
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70108244978720
35
+ version_requirements: *70117859350560
36
36
  description: Truncates html so you don't have to
37
37
  email:
38
38
  - harold.gimenez@gmail.com
@@ -99,7 +99,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
99
99
  version: '0'
100
100
  segments:
101
101
  - 0
102
- hash: -2387288071087328503
102
+ hash: 2344297215831564369
103
103
  required_rubygems_version: !ruby/object:Gem::Requirement
104
104
  none: false
105
105
  requirements:
@@ -108,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
108
  version: '0'
109
109
  segments:
110
110
  - 0
111
- hash: -2387288071087328503
111
+ hash: 2344297215831564369
112
112
  requirements: []
113
113
  rubyforge_project:
114
114
  rubygems_version: 1.8.10