truncate_html 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,2 +1,4 @@
1
1
  pkg
2
2
  coverage
3
+ profiling
4
+ tmp
data/History.txt CHANGED
@@ -1,5 +1,5 @@
1
1
  == 0.2.2 2009-12-23
2
- * Fix issue #4: Handle case when supplied length is smaller than omission (ghazel)
2
+ * Fix issue #4: Handle case when supplied length is smaller than omission. (ghazel)
3
3
 
4
4
  == 0.2.1 2009-12-18
5
5
  * Fix issue #3: Handle case when input html contins a script tag.
@@ -10,7 +10,7 @@
10
10
  helper's behavior.
11
11
 
12
12
  == 0.1.2 2009-09-25
13
- * Fix issue #1: Handle case when input html is nil.
13
+ * Fix issue #1: Handle case when input html is nil. (bcardarella)
14
14
 
15
15
  == 0.1.1 2009-08-25
16
16
  * Fixed issue with regex which would not recognize <a> tags that contain slashes.
data/README.markdown CHANGED
@@ -3,25 +3,26 @@ TruncateHtml
3
3
 
4
4
  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/).
5
5
 
6
- The API is very similar to Rails' own truncate method.
6
+ The API is very similar to Rails' own <code>truncate()</code> method.
7
7
 
8
8
 
9
9
  Example
10
10
  -------
11
11
 
12
12
  some_html = '<ul><li><a href="http://whatever">This is a link</a></li></ul>'
13
-
14
- truncate_html(some_html, :length => 5, :omission => '...(continued)')
15
-
16
- => <ul><li><a href="http://whatever">This is...(continued)</a></li></ul>
17
-
13
+ truncate_html(some_html, :length => 15, :omission => '...(continued)')
14
+ => <ul><li><a href="http://whatever">This...(continued)</a></li></ul>
18
15
 
19
16
  A few notes:
20
17
 
21
- * It will truncate on a word boundary.
22
18
  * The default options are:
23
19
  * :length => 100
24
20
  * :omission => '...'
21
+ * By default, it will truncate on word boundry.
22
+ To truncate the HTML string strictly at the specified length, pass in the `:word_boundry => false` option.
23
+ * If the input HTML is nil, it will return an empty string.
24
+ * The omission text's length does count toward the resulting string's length.
25
+ * `<script>` tags will pass right through - they will not count toward the resulting string's length, or be truncated.
25
26
 
26
27
  Installation
27
28
  ------------
@@ -33,9 +34,9 @@ Add this to your <code>config/environment.rb</code>:
33
34
  :source => 'http://gemcutter.org'
34
35
 
35
36
  Then either
36
- <code>sudo rake gems:install</code>
37
+ <code>rake gems:install</code>
37
38
  or
38
- <code>sudo gem install truncate_html</code>
39
+ <code>gem install truncate_html</code>
39
40
 
40
41
  #### As a plugin:
41
42
  <code>script/plugin install git://github.com/hgimenez/truncate_html.git</code>
@@ -50,4 +51,13 @@ Testing
50
51
 
51
52
  The plugin is tested using RSpec. [Install it](http://wiki.github.com/dchelimsky/rspec/rails) on your app if you wish to run the tests.
52
53
 
54
+ If you want to hack on this, here's how to set up a development/testing environment:
55
+
56
+ $ rails truncate_html_base
57
+ $ cd truncate_html_base
58
+ $ git clone git://github.com/hgimenez/truncate_html.git vendor/plugins/truncate_html
59
+ # install RSpec, follow instructions at http://wiki.github.com/dchelimsky/rspec/rails
60
+ $ cd vendor/plugins/truncate_html
61
+ $ rake spec # all green? Go hack
62
+
53
63
  Copyright (c) 2009 Harold A. Giménez, released under the MIT license
data/Rakefile CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'rake'
2
2
  require 'spec/rake/spectask'
3
3
 
4
+
4
5
  desc 'Default: run specs.'
5
6
  task :default => :spec
6
7
 
@@ -16,6 +17,24 @@ Spec::Rake::SpecTask.new(:rcov) do |spec|
16
17
  spec.rcov = true
17
18
  end
18
19
 
20
+ begin
21
+ require 'metric_fu'
22
+ MetricFu::Configuration.run do |config|
23
+ config.metrics = [:saikuro, :flog, :flay, :reek, :roodi, :rcov]
24
+ config.graphs = [:flog, :flay, :reek, :roodi, :rcov]
25
+ config.rcov = { :environment => 'test',
26
+ :test_files => ['spec/**/*_spec.rb'],
27
+ :rcov_opts => ["--sort coverage",
28
+ "--text-coverage",
29
+ "--profile",
30
+ "--exclude /gems/,/Library/"]}
31
+ config.graph_engine = :bluff
32
+ end
33
+ rescue LoadError
34
+ puts "Install metric_fu to run code metrics"
35
+ end
36
+
37
+
19
38
  begin
20
39
  require 'jeweler'
21
40
  Jeweler::Tasks.new do |gem|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.3.0
data/init.rb CHANGED
@@ -1 +1,7 @@
1
1
  require 'truncate_html'
2
+
3
+ TruncateHtml.configure do |config|
4
+ config.length = 100
5
+ config.omission = '...'
6
+ config.word_boundry = true
7
+ end
@@ -1,7 +1,9 @@
1
1
  module TruncateHtmlHelper
2
2
 
3
3
  def truncate_html(html, options={})
4
- TruncateHtml::HtmlTruncator.new(html).truncate(options)
4
+ return '' if html.nil?
5
+ html_string = TruncateHtml::HtmlString.new(html)
6
+ TruncateHtml::HtmlTruncator.new(html_string).truncate(options)
5
7
  end
6
8
 
7
9
  end
data/lib/truncate_html.rb CHANGED
@@ -1,9 +1,6 @@
1
- path = File.join(File.dirname(__FILE__), 'app', 'helpers')
2
- $LOAD_PATH << path
3
- ActiveSupport::Dependencies.load_paths << path
4
- ActiveSupport::Dependencies.load_once_paths.delete(path)
5
-
6
1
  require File.join(File.dirname(__FILE__), 'truncate_html', 'html_truncator')
2
+ require File.join(File.dirname(__FILE__), 'truncate_html', 'configuration')
3
+ require File.join(File.dirname(__FILE__), 'app', 'helpers', 'truncate_html_helper')
7
4
 
8
5
  ActionView::Base.class_eval do
9
6
  include TruncateHtmlHelper
@@ -0,0 +1,15 @@
1
+ module TruncateHtml
2
+ class Configuration
3
+ attr_accessor :length, :omission, :word_boundry
4
+ end
5
+
6
+ class << self
7
+ attr_accessor :configuration
8
+ end
9
+
10
+ def self.configure
11
+ self.configuration ||= Configuration.new
12
+ yield configuration
13
+ end
14
+
15
+ end
@@ -0,0 +1,35 @@
1
+ module TruncateHtml
2
+ class HtmlString < String
3
+
4
+ UNPAIRED_TAGS = %w(br hr img)
5
+
6
+ def initialize(original_html)
7
+ super(original_html)
8
+ end
9
+
10
+ def html_tokens
11
+ scan(/(?:<script.*>.*<\/script>)+|<\/?[^>]+>|[\w\|`~!@#\$%^&*\(\)\-_\+=\[\]{}:;'",\.\/?]+|\s+/).map do
12
+ |token| token.gsub(
13
+ #remove newline characters
14
+ /\n/,''
15
+ ).gsub(
16
+ #clean out extra consecutive whitespace
17
+ /\s+/, ' '
18
+ )
19
+ end.map { |token| HtmlString.new(token) }
20
+ end
21
+
22
+ def html_tag?
23
+ self =~ /<\/?[^>]+>/ ? true : false
24
+ end
25
+
26
+ def open_tag?
27
+ self =~ /<(?!(?:#{UNPAIRED_TAGS.join('|')}|script|\/))[^>]+>/i ? true : false
28
+ end
29
+
30
+ def matching_close_tag
31
+ gsub(/<(\w+)\s?.*>/, '</\1>').strip
32
+ end
33
+
34
+ end
35
+ end
@@ -1,74 +1,67 @@
1
1
  module TruncateHtml
2
2
  class HtmlTruncator
3
3
 
4
- UNPAIRED_TAGS = %w(br hr img)
5
-
6
4
  def initialize(original_html)
7
- @original_html = original_html
5
+ @original_html = original_html
8
6
  end
9
7
 
10
8
  def truncate(options = {})
11
- return '' if @original_html.nil?
12
- options[:length] ||= 100
13
- options[:omission] ||= '...'
14
- @chars_remaining = options[:length] - options[:omission].length
15
- @open_tags, result = [], ['']
9
+ length = options[:length] || TruncateHtml.configuration.length
10
+ @omission = options[:omission] || TruncateHtml.configuration.omission
11
+ @word_boundry = (options.has_key?(:word_boundry) ? options[:word_boundry] : TruncateHtml.configuration.word_boundry)
12
+ @chars_remaining = length - @omission.length
13
+ @open_tags, @truncated_html = [], ['']
16
14
 
17
- html_tokens.each do |str|
15
+ @original_html.html_tokens.each do |token|
16
+ #if truncate_more?(token)
18
17
  if @chars_remaining > 0
19
- if html_tag?(str)
20
- if open_tag?(str)
21
- @open_tags << str
22
- else
23
- open_tags = remove_latest_open_tag(str)
24
- end
25
- else
26
- @chars_remaining -= str.length
27
- end
28
- result << str
18
+ process_token(token)
29
19
  else
30
- result[-1] = result[-1].rstrip + options[:omission]
31
- @open_tags.reverse_each do |open_tag|
32
- result << matching_close_tag(open_tag)
33
- end
20
+ close_open_tags
34
21
  break
35
22
  end
36
23
  end
37
- result.join('')
24
+ @truncated_html.join
38
25
  end
39
26
 
40
- def html_tokens
41
- @original_html.scan(/(?:<script.*>.*<\/script>)+|<\/?[^>]+>|[\w\|`~!@#\$%^&*\(\)\-_\+=\[\]{}:;'",\.\/?]+|\s+/).map do
42
- |t| t.gsub(
43
- #remove newline characters
44
- /\n/,''
45
- ).gsub(
46
- #clean out extra consecutive whitespace
47
- /\s+/, ' '
48
- )
49
- end
50
- end
27
+ private
51
28
 
52
- def html_tag?(string)
53
- string =~ /<\/?[^>]+>/ ? true : false
54
- end
29
+ def process_token(token)
30
+ append_to_result(token)
31
+ if token.html_tag?
32
+ if token.open_tag?
33
+ @open_tags << token
34
+ else
35
+ remove_latest_open_tag(token)
36
+ end
37
+ else
38
+ @chars_remaining -= (@word_boundry ? token.length : token[0, @chars_remaining].length)
39
+ end
40
+ end
55
41
 
56
- def open_tag?(html_tag)
57
- html_tag =~ /<(?!(?:#{UNPAIRED_TAGS.join('|')}|script|\/))[^>]+>/i ? true : false
58
- end
42
+ def append_to_result(token)
43
+ if @word_boundry
44
+ @truncated_html << token
45
+ else
46
+ @truncated_html << token[0, @chars_remaining]
47
+ end
48
+ end
59
49
 
60
- def remove_latest_open_tag(close_tag)
61
- (0...@open_tags.length).to_a.reverse.each do |i|
62
- if matching_close_tag(@open_tags[i]) == close_tag
63
- @open_tags.delete_at(i)
64
- break
50
+ def close_open_tags
51
+ @truncated_html[-1] = @truncated_html[-1].rstrip + @omission
52
+ @open_tags.reverse_each do |open_tag|
53
+ @truncated_html << open_tag.matching_close_tag
65
54
  end
66
55
  end
67
- end
68
56
 
69
- def matching_close_tag(open_tag)
70
- open_tag.gsub(/<(\w+)\s?.*>/, '</\1>').strip
71
- end
57
+ def remove_latest_open_tag(close_tag)
58
+ (0...@open_tags.length).to_a.reverse.each do |index|
59
+ if @open_tags[index].matching_close_tag == close_tag
60
+ @open_tags.delete_at(index)
61
+ break
62
+ end
63
+ end
64
+ end
72
65
 
73
66
  end
74
67
  end
@@ -2,115 +2,40 @@ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
2
 
3
3
  include TruncateHtmlHelper
4
4
 
5
+ class Truncator
6
+ include TruncateHtmlHelper
7
+ end
8
+
5
9
  describe TruncateHtmlHelper do
6
10
 
11
+ def truncator
12
+ @truncator ||= Truncator.new
13
+ end
14
+
7
15
  it 'is included in ActionView::Base' do
8
16
  ActionView::Base.included_modules.should include(TruncateHtmlHelper)
9
17
  end
10
18
 
11
- describe '#truncate_html' do
12
-
13
- it "includes the omission text's length in the returned truncated html" do
14
- truncate_html('a b c', :length => 4, :omission => '...').should == 'a...'
15
- end
16
-
17
- it 'supports omissions longer than the maximum length' do
18
- lambda { truncate_html('', :length => 1, :omission => '...') }.should_not raise_error
19
- end
20
-
21
- it 'returns the omission when the specified length is smaller than the omission' do
22
- truncate_html('a b c', :length => 2, :omission => '...').should == '...'
23
- end
24
-
25
- context 'the input html is nil' do
26
- it 'returns an empty string' do
27
- truncate_html(nil).should be_empty
28
- truncate_html(nil).should be_kind_of(String)
29
- end
30
- end
31
-
32
- context 'the input html contains a script tag' do
33
- before(:each) do
34
- @input_html = "<p>I have a script <script type=text/javascript>document.write('lum dee dum');</script> and more text</p>"
35
- @expected_out = "<p>I have a script <script type=text/javascript>document.write('lum dee dum');</script> and...</p>"
36
- end
37
- it 'treats the script tag as lengthless string' do
38
- truncate_html(@input_html, :length => 23).should == @expected_out
39
- end
40
- end
41
-
42
- context 'truncating in the middle of a link' do
43
- before(:each) do
44
- @html = '<div><ul><li>Look at <a href="foo">this</a> link </li></ul></div>'
45
- end
46
-
47
- it 'truncates, and closes the <a>, and closes any remaining open tags' do
48
- truncate_html(@html, :length => 14).should == '<div><ul><li>Look at <a href="foo">this...</a></li></ul></div>'
49
- end
50
- end
51
-
52
- %w(! @ # $ % ^ & * \( \) - _ + = [ ] { } \ | , . / ?).each do |char|
53
- context "when the html has a #{char} character after a closing tag" do
54
- before(:each) do
55
- @html = "<p>Look at <strong>this</strong>#{char} More words here</p>"
56
- end
57
- it 'places the punctuation after the tag without any whitespace' do
58
- truncate_html(@html, :length => 19).should == "<p>Look at <strong>this</strong>#{char} More...</p>"
59
- end
60
- end
61
- end
62
-
63
- context 'when the html has a non punctuation character after a closing tag' do
64
- before(:each) do
65
- @html = '<p>Look at <a href="awesomeful.net">this</a> link for randomness</p>'
66
- end
67
- it 'leaves a whitespace between the closing tag and the following word character' do
68
- truncate_html(@html, :length => 21).should == '<p>Look at <a href="awesomeful.net">this</a> link...</p>'
69
- end
70
- end
71
-
72
- #unusual, but just covering my ass
73
- context 'when the HTML tags are multiline' do
74
- before(:each) do
75
- @html = <<-END_HTML
76
- <div id="foo"
77
- class="bar">
78
- This is ugly html.
79
- </div>
80
- END_HTML
81
- end
82
-
83
- it 'recognizes the multiline html properly' do
84
- truncate_html(@html, :length => 12).should == ' <div id="foo" class="bar"> This is...</div>'
85
- end
86
- end
87
-
88
- %w(br hr img).each do |unpaired_tag|
89
- context "when the html contains a #{unpaired_tag} tag" do
19
+ before(:each) do
20
+ @html_truncator_mock = mock(TruncateHtml::HtmlTruncator)
21
+ end
90
22
 
91
- context "and the #{unpaired_tag} does not have the closing slash" do
92
- before(:each) do
93
- @html = "<div>Some before. <#{unpaired_tag}>and some after</div>"
94
- @html_caps = "<div>Some before. <#{unpaired_tag.capitalize}>and some after</div>"
95
- end
96
- it "does not close the #{unpaired_tag} tag" do
97
- truncate_html(@html, :length => 19).should == "<div>Some before. <#{unpaired_tag}>and...</div>"
98
- truncate_html(@html_caps, :length => 19).should == "<div>Some before. <#{unpaired_tag.capitalize}>and...</div>"
99
- end
100
- end
23
+ it 'creates an instance of HtmlTruncator and calls truncate() on it' do
24
+ @html_truncator_mock.stub!(:truncate)
25
+ TruncateHtml::HtmlTruncator.should_receive(:new).and_return(@html_truncator_mock)
26
+ truncator.truncate_html('foo')
27
+ end
101
28
 
102
- context "and the #{unpaired_tag} does have the closing slash" do
103
- before(:each) do
104
- @html = "<div>Some before. <#{unpaired_tag} />and some after</div>"
105
- @html_caps = "<div>Some before. <#{unpaired_tag.capitalize} />and some after</div>"
106
- end
107
- it "does not close the #{unpaired_tag} tag" do
108
- truncate_html(@html, :length => 19).should == "<div>Some before. <#{unpaired_tag} />and...</div>"
109
- truncate_html(@html_caps, :length => 19).should == "<div>Some before. <#{unpaired_tag.capitalize} />and...</div>"
110
- end
111
- end
29
+ it 'calls truncate() on the HtmlTruncator object' do
30
+ TruncateHtml::HtmlTruncator.stub!(:new).and_return(@html_truncator_mock)
31
+ @html_truncator_mock.should_receive(:truncate).with({}).once
32
+ truncator.truncate_html('foo')
33
+ end
112
34
 
113
- end
35
+ context 'the input html is nil' do
36
+ it 'returns an empty string' do
37
+ truncator.truncate_html(nil).should be_empty
38
+ truncator.truncate_html(nil).should be_kind_of(String)
114
39
  end
115
40
  end
116
41
 
data/spec/spec_helper.rb CHANGED
@@ -6,4 +6,4 @@ rescue LoadError
6
6
  end
7
7
 
8
8
  plugin_spec_dir = File.dirname(__FILE__)
9
- require File.join(File.dirname(__FILE__), '..', 'lib', 'app', 'helpers', 'truncate_html_helper')
9
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'truncate_html')
@@ -0,0 +1,17 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe TruncateHtml::Configuration do
4
+
5
+ describe 'self.configure' do
6
+
7
+ it 'yields the configuration object' do
8
+ lambda do
9
+ TruncateHtml.configure do |config|
10
+ config.should be_kind_of(TruncateHtml::Configuration)
11
+ throw :yay_it_yielded
12
+ end
13
+ end.should throw_symbol(:yay_it_yielded)
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,76 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe TruncateHtml::HtmlString do
4
+
5
+ def html_string(original_string)
6
+ TruncateHtml::HtmlString.new(original_string)
7
+ end
8
+
9
+ describe '#html_tokens' do
10
+ before(:each) do
11
+ @html = '<h1>Hi there</h1> <p>This is sweet!</p>'
12
+ end
13
+
14
+ it 'returns each token in the string as an array element removing any consecutive whitespace from the string' do
15
+ html_string(@html).html_tokens.should == ['<h1>', 'Hi', ' ', 'there', '</h1>', ' ', '<p>', 'This', ' ', 'is', ' ', 'sweet!', '</p>']
16
+ end
17
+
18
+ end
19
+
20
+ describe '#html_tag?' do
21
+
22
+ it 'returns false when the string parameter is not an html tag' do
23
+ html_string('no tags').html_tag?.should be_false
24
+ end
25
+
26
+ it 'returns true when the string parameter is an html tag' do
27
+ html_string('<img src="foo">').html_tag?.should be_true
28
+ html_string('</img>').html_tag?.should be_true
29
+ end
30
+
31
+ end
32
+
33
+ describe '#open_tag?' do
34
+
35
+ it 'returns true if the tag is an open tag' do
36
+ html_string('<a>').open_tag?.should be_true
37
+ end
38
+
39
+ context 'the tag is an open tag, and has whitespace and html properties' do
40
+ it 'returns true if it has single quotes' do
41
+ html_string(" <a href='http://awesomeful.net' >").open_tag?.should be_true
42
+ end
43
+
44
+ it 'returns true if it has double quotes' do
45
+ html_string(' <a href="http://awesomeful.net">').open_tag?.should be_true
46
+ end
47
+ end
48
+
49
+ it 'returns false if the tag is a close tag' do
50
+ html_string('</a>').open_tag?.should be_false
51
+ end
52
+
53
+ it 'returns false if the string is not an html tag' do
54
+ html_string('foo bar').open_tag?.should be_false
55
+ end
56
+
57
+ it 'returns false if it is a <script> tag' do
58
+ html_string('<script>').open_tag?.should be_false
59
+ end
60
+ end
61
+
62
+ describe '#matching_close_tag' do
63
+ tag_pairs = { '<a>' => '</a>',
64
+ ' <div>' => '</div>',
65
+ '<h1>' => '</h1>',
66
+ '<a href="foo">' => '</a>' }
67
+
68
+ tag_pairs.each do |open_tag, close_tag|
69
+ it "closes a #{open_tag} and returns #{close_tag}" do
70
+ html_string(open_tag).matching_close_tag.should == close_tag
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+ end
@@ -2,73 +2,113 @@ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
2
 
3
3
  describe TruncateHtml::HtmlTruncator do
4
4
 
5
- def truncator(html = nil)
6
- @truncator ||= TruncateHtml::HtmlTruncator.new(html)
5
+ def truncate(html, opts = {})
6
+ html_string = TruncateHtml::HtmlString.new(html)
7
+ TruncateHtml::HtmlTruncator.new(html_string).truncate(opts)
7
8
  end
8
9
 
9
- describe '#html_tokens' do
10
- before(:each) do
11
- @html = '<h1>Hi there</h1> <p>This is sweet!</p>'
12
- end
10
+ describe '#truncate' do
13
11
 
14
- it 'returns each token in the string as an array element removing any consecutive whitespace from the string' do
15
- truncator(@html).html_tokens.should == ['<h1>', 'Hi', ' ', 'there', '</h1>', ' ', '<p>', 'This', ' ', 'is', ' ', 'sweet!', '</p>']
12
+ context 'when the word_boundry option is set to false' do
13
+ it 'truncates to the exact length specified' do
14
+ truncate('<div>123456789</div>', :length => 5, :omission => '', :word_boundry => false).should == '<div>12345</div>'
15
+ end
16
16
  end
17
17
 
18
- end
19
-
20
- describe '#html_tag?' do
21
-
22
- it 'returns false when the string parameter is not an html tag' do
23
- truncator.html_tag?('no tags').should be_false
18
+ it "includes the omission text's length in the returned truncated html" do
19
+ truncate('a b c', :length => 4, :omission => '...').should == 'a...'
24
20
  end
25
21
 
26
- it 'returns true when the string parameter is an html tag' do
27
- truncator.html_tag?('<img src="foo">').should be_true
28
- truncator.html_tag?('</img>').should be_true
22
+ it 'supports omissions longer than the maximum length' do
23
+ lambda { truncate('', :length => 1, :omission => '...') }.should_not raise_error
29
24
  end
30
25
 
31
- end
32
-
33
- describe '#open_tag?' do
34
-
35
- it 'returns true if the tag is an open tag' do
36
- truncator.open_tag?('<a>').should be_true
26
+ it 'returns the omission when the specified length is smaller than the omission' do
27
+ truncate('a b c', :length => 2, :omission => '...').should == '...'
37
28
  end
38
29
 
39
- it 'returns true if the tag is an open tag, and has whitespace and html properties with either single or double quotes' do
40
- truncator.open_tag?(' <a href="http://awesomeful.net">').should be_true
41
- truncator.open_tag?(" <a href='http://awesomeful.net' >").should be_true
30
+ context 'the input html contains a script tag' do
31
+ before(:each) do
32
+ @input_html = "<p>I have a script <script type=text/javascript>document.write('lum dee dum');</script> and more text</p>"
33
+ @expected_out = "<p>I have a script <script type=text/javascript>document.write('lum dee dum');</script> and...</p>"
34
+ end
35
+ it 'treats the script tag as lengthless string' do
36
+ truncate(@input_html, :length => 23).should == @expected_out
37
+ end
42
38
  end
43
39
 
44
- it 'returns false if the tag is a close tag' do
45
- truncator.open_tag?('</a>').should be_false
46
- end
40
+ context 'truncating in the middle of a link' do
41
+ before(:each) do
42
+ @html = '<div><ul><li>Look at <a href="foo">this</a> link </li></ul></div>'
43
+ end
47
44
 
48
- it 'returns false if the string is not an html tag' do
49
- truncator.open_tag?('foo bar').should be_false
45
+ it 'truncates, and closes the <a>, and closes any remaining open tags' do
46
+ truncate(@html, :length => 14).should == '<div><ul><li>Look at <a href="foo">this...</a></li></ul></div>'
47
+ end
50
48
  end
51
49
 
52
- it 'returns false if it is a <script> tag' do
53
- truncator.open_tag?('<script>').should be_false
50
+ %w(! @ # $ % ^ & * \( \) - _ + = [ ] { } \ | , . / ?).each do |char|
51
+ context "when the html has a #{char} character after a closing tag" do
52
+ before(:each) do
53
+ @html = "<p>Look at <strong>this</strong>#{char} More words here</p>"
54
+ end
55
+ it 'places the punctuation after the tag without any whitespace' do
56
+ truncate(@html, :length => 19).should == "<p>Look at <strong>this</strong>#{char} More...</p>"
57
+ end
58
+ end
54
59
  end
55
- end
56
60
 
57
- describe '#matching_close_tag' do
58
-
59
- it 'closes a tag given an open tag' do
60
- truncator.matching_close_tag('<a>').should == '</a>'
61
- truncator.matching_close_tag(' <div>').should == '</div>'
62
- truncator.matching_close_tag('<h1>').should == '</h1>'
63
- truncator.matching_close_tag('<a href="foo">').should == '</a>'
61
+ context 'when the html has a non punctuation character after a closing tag' do
62
+ before(:each) do
63
+ @html = '<p>Look at <a href="awesomeful.net">this</a> link for randomness</p>'
64
+ end
65
+ it 'leaves a whitespace between the closing tag and the following word character' do
66
+ truncate(@html, :length => 21).should == '<p>Look at <a href="awesomeful.net">this</a> link...</p>'
67
+ end
64
68
  end
65
- end
66
69
 
67
- describe 'nil string' do
70
+ #unusual, but just covering my ass
71
+ context 'when the HTML tags are multiline' do
72
+ before(:each) do
73
+ @html = <<-END_HTML
74
+ <div id="foo"
75
+ class="bar">
76
+ This is ugly html.
77
+ </div>
78
+ END_HTML
79
+ end
80
+
81
+ it 'recognizes the multiline html properly' do
82
+ truncate(@html, :length => 12).should == ' <div id="foo" class="bar"> This is...</div>'
83
+ end
84
+ end
68
85
 
69
- it 'returns an empty string' do
70
- truncator(nil).truncate.should be_empty
71
- truncator(nil).truncate.should be_kind_of(String)
86
+ %w(br hr img).each do |unpaired_tag|
87
+ context "when the html contains a #{unpaired_tag} tag" do
88
+
89
+ context "and the #{unpaired_tag} does not have the closing slash" do
90
+ before(:each) do
91
+ @html = "<div>Some before. <#{unpaired_tag}>and some after</div>"
92
+ @html_caps = "<div>Some before. <#{unpaired_tag.capitalize}>and some after</div>"
93
+ end
94
+ it "does not close the #{unpaired_tag} tag" do
95
+ truncate(@html, :length => 19).should == "<div>Some before. <#{unpaired_tag}>and...</div>"
96
+ truncate(@html_caps, :length => 19).should == "<div>Some before. <#{unpaired_tag.capitalize}>and...</div>"
97
+ end
98
+ end
99
+
100
+ context "and the #{unpaired_tag} does have the closing slash" do
101
+ before(:each) do
102
+ @html = "<div>Some before. <#{unpaired_tag} />and some after</div>"
103
+ @html_caps = "<div>Some before. <#{unpaired_tag.capitalize} />and some after</div>"
104
+ end
105
+ it "does not close the #{unpaired_tag} tag" do
106
+ truncate(@html, :length => 19).should == "<div>Some before. <#{unpaired_tag} />and...</div>"
107
+ truncate(@html_caps, :length => 19).should == "<div>Some before. <#{unpaired_tag.capitalize} />and...</div>"
108
+ end
109
+ end
110
+
111
+ end
72
112
  end
73
113
  end
74
114
 
@@ -1,15 +1,15 @@
1
1
  # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{truncate_html}
8
- s.version = "0.2.2"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["hgimenez"]
12
- s.date = %q{2009-12-23}
12
+ s.date = %q{2010-02-02}
13
13
  s.description = %q{Truncates html so you don't have to}
14
14
  s.email = %q{harold.gimenez@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -25,9 +25,13 @@ Gem::Specification.new do |s|
25
25
  "install.rb",
26
26
  "lib/app/helpers/truncate_html_helper.rb",
27
27
  "lib/truncate_html.rb",
28
+ "lib/truncate_html/configuration.rb",
29
+ "lib/truncate_html/html_string.rb",
28
30
  "lib/truncate_html/html_truncator.rb",
29
31
  "spec/helpers/truncate_html_helper_spec.rb",
30
32
  "spec/spec_helper.rb",
33
+ "spec/truncate_html/configuration_spec.rb",
34
+ "spec/truncate_html/html_string_spec.rb",
31
35
  "spec/truncate_html/html_truncator_spec.rb",
32
36
  "tasks/truncate_html_tasks.rake",
33
37
  "truncate_html.gemspec",
@@ -41,6 +45,8 @@ Gem::Specification.new do |s|
41
45
  s.test_files = [
42
46
  "spec/helpers/truncate_html_helper_spec.rb",
43
47
  "spec/spec_helper.rb",
48
+ "spec/truncate_html/configuration_spec.rb",
49
+ "spec/truncate_html/html_string_spec.rb",
44
50
  "spec/truncate_html/html_truncator_spec.rb"
45
51
  ]
46
52
 
@@ -54,3 +60,4 @@ Gem::Specification.new do |s|
54
60
  else
55
61
  end
56
62
  end
63
+
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.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - hgimenez
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-23 00:00:00 -05:00
12
+ date: 2010-02-02 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -31,9 +31,13 @@ files:
31
31
  - install.rb
32
32
  - lib/app/helpers/truncate_html_helper.rb
33
33
  - lib/truncate_html.rb
34
+ - lib/truncate_html/configuration.rb
35
+ - lib/truncate_html/html_string.rb
34
36
  - lib/truncate_html/html_truncator.rb
35
37
  - spec/helpers/truncate_html_helper_spec.rb
36
38
  - spec/spec_helper.rb
39
+ - spec/truncate_html/configuration_spec.rb
40
+ - spec/truncate_html/html_string_spec.rb
37
41
  - spec/truncate_html/html_truncator_spec.rb
38
42
  - tasks/truncate_html_tasks.rake
39
43
  - truncate_html.gemspec
@@ -69,4 +73,6 @@ summary: Uses an API similar to Rails' truncate helper to truncate HTML and clos
69
73
  test_files:
70
74
  - spec/helpers/truncate_html_helper_spec.rb
71
75
  - spec/spec_helper.rb
76
+ - spec/truncate_html/configuration_spec.rb
77
+ - spec/truncate_html/html_string_spec.rb
72
78
  - spec/truncate_html/html_truncator_spec.rb