trunction 0.0.1
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.
- data/.gitignore +4 -0
- data/Gemfile +7 -0
- data/Rakefile +9 -0
- data/lib/trunction/version.rb +3 -0
- data/lib/trunction.rb +71 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/trunction_spec.rb +92 -0
- data/trunction.gemspec +23 -0
- metadata +66 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
data/lib/trunction.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require "trunction/version"
|
2
|
+
require "nokogiri"
|
3
|
+
|
4
|
+
module Trunction
|
5
|
+
|
6
|
+
extend self
|
7
|
+
|
8
|
+
def truncate_html(html, max)
|
9
|
+
doc = Nokogiri::HTML::DocumentFragment.parse(html)
|
10
|
+
Truncation.new(doc, max).execute
|
11
|
+
doc.to_html
|
12
|
+
end
|
13
|
+
|
14
|
+
class Truncation
|
15
|
+
|
16
|
+
def initialize(doc, max)
|
17
|
+
@doc = doc
|
18
|
+
@max = max
|
19
|
+
@chars_remaining = max
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute
|
23
|
+
find_the_end
|
24
|
+
remove_everything_else
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def find_the_end
|
30
|
+
catch(:done) do
|
31
|
+
@doc.traverse do |node|
|
32
|
+
accumulate_text(node) if node.text?
|
33
|
+
record(node)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def accumulate_text(text_node)
|
39
|
+
@chars_remaining -= text_node.text.length
|
40
|
+
throw(:done) if limit_reached?
|
41
|
+
end
|
42
|
+
|
43
|
+
def limit_reached?
|
44
|
+
@chars_remaining <= 0
|
45
|
+
end
|
46
|
+
|
47
|
+
def record(node)
|
48
|
+
@last_block_element = node if block?(node)
|
49
|
+
@last_element = node
|
50
|
+
end
|
51
|
+
|
52
|
+
def last_node
|
53
|
+
@last_block_element || @last_element
|
54
|
+
end
|
55
|
+
|
56
|
+
def block?(node)
|
57
|
+
node.description && node.description.block?
|
58
|
+
end
|
59
|
+
|
60
|
+
def remove_everything_else
|
61
|
+
node = last_node
|
62
|
+
while node
|
63
|
+
node.next.remove while node.next
|
64
|
+
break unless node.respond_to?(:parent)
|
65
|
+
node = node.parent
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'trunction'
|
2
|
+
|
3
|
+
describe Trunction do
|
4
|
+
|
5
|
+
let(:total_length) { Nokogiri::HTML::DocumentFragment.parse(input).text.length }
|
6
|
+
let(:ellipsis) { "…" }
|
7
|
+
|
8
|
+
include Trunction
|
9
|
+
|
10
|
+
let(:result) do
|
11
|
+
truncate_html(input, max_length).gsub("\n", '')
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#truncate_html" do
|
15
|
+
|
16
|
+
context "given multiple paragraphs" do
|
17
|
+
|
18
|
+
let(:input) { "<p>one</p><p>two</p><p>three</p>" }
|
19
|
+
|
20
|
+
context "with max-length longer than input" do
|
21
|
+
|
22
|
+
let(:max_length) { total_length + 1 }
|
23
|
+
|
24
|
+
it "returns input intact" do
|
25
|
+
result.should == input
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
context "with max-length shorter than input" do
|
31
|
+
|
32
|
+
let(:max_length) { total_length - 1 }
|
33
|
+
|
34
|
+
it "drops elements until beneath max-length" do
|
35
|
+
result.should == "<p>one</p><p>two</p>"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
context "given multiple paragraphs, wrapped in a div" do
|
43
|
+
|
44
|
+
let(:input) { "<div><p>one</p><p>two</p><p>three</p></div>" }
|
45
|
+
|
46
|
+
context "with max-length shorter than input" do
|
47
|
+
|
48
|
+
let(:max_length) { total_length - 1 }
|
49
|
+
|
50
|
+
it "drops elements until beneath max-length" do
|
51
|
+
result.should == "<div><p>one</p><p>two</p></div>"
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
context "a single paragraph with inline elements" do
|
59
|
+
|
60
|
+
let(:input) { "<p><b>one</b>, <b>two</b>, <b>three</b>, <b>four</b></p>" }
|
61
|
+
|
62
|
+
context "with max-length shorter than input" do
|
63
|
+
|
64
|
+
let(:max_length) { total_length - 1 }
|
65
|
+
|
66
|
+
it "drops the last word" do
|
67
|
+
result.should == "<p><b>one</b>, <b>two</b>, <b>three</b>, </p>"
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
context "a final paragraph with inline elements" do
|
75
|
+
|
76
|
+
let(:input) { "<p>one</p><p>two</p><p><b>one</b>, <b>two</b>, <b>three</b>, <b>four</b></p>" }
|
77
|
+
|
78
|
+
context "with max-length shorter than input" do
|
79
|
+
|
80
|
+
let(:max_length) { total_length - 1 }
|
81
|
+
|
82
|
+
it "drops the entire final paragraph" do
|
83
|
+
result.should == "<p>one</p><p>two</p>"
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
data/trunction.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "trunction/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "trunction"
|
7
|
+
s.version = Trunction::VERSION
|
8
|
+
s.authors = ["Mike Williams"]
|
9
|
+
s.email = ["mdub@dogbiscuit.org"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Beat your HTML down to size}
|
12
|
+
s.description = %q{Trunction implements intelligent truncation of HTML text.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "trunction"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_runtime_dependency "nokogiri"
|
22
|
+
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: trunction
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mike Williams
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-12-05 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: nokogiri
|
16
|
+
requirement: &70261283968360 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70261283968360
|
25
|
+
description: Trunction implements intelligent truncation of HTML text.
|
26
|
+
email:
|
27
|
+
- mdub@dogbiscuit.org
|
28
|
+
executables: []
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- .gitignore
|
33
|
+
- Gemfile
|
34
|
+
- Rakefile
|
35
|
+
- lib/trunction.rb
|
36
|
+
- lib/trunction/version.rb
|
37
|
+
- spec/spec_helper.rb
|
38
|
+
- spec/trunction_spec.rb
|
39
|
+
- trunction.gemspec
|
40
|
+
homepage: ''
|
41
|
+
licenses: []
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ! '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
requirements: []
|
59
|
+
rubyforge_project: trunction
|
60
|
+
rubygems_version: 1.8.10
|
61
|
+
signing_key:
|
62
|
+
specification_version: 3
|
63
|
+
summary: Beat your HTML down to size
|
64
|
+
test_files:
|
65
|
+
- spec/spec_helper.rb
|
66
|
+
- spec/trunction_spec.rb
|