tweet_compressor 0.8.2
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 +50 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/AUTHORS +2 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +48 -0
- data/Guardfile +5 -0
- data/LICENSE +676 -0
- data/README.md +125 -0
- data/Rakefile +55 -0
- data/bin/tweet_compressor +14 -0
- data/lib/tweet_compressor.rb +7 -0
- data/lib/tweet_compressor/compress.rb +187 -0
- data/lib/tweet_compressor/tweet.rb +38 -0
- data/lib/tweet_compressor/version.rb +3 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/tweet_compressor_spec.rb +274 -0
- data/tweet_compressor.gemspec +26 -0
- metadata +75 -0
@@ -0,0 +1,274 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TweetCompressor::Tweet do
|
4
|
+
let(:filler ) { ?X * 140 }
|
5
|
+
let(:space ) { ' ' }
|
6
|
+
let(:string1) { 'Something wicked this way comes.' }
|
7
|
+
let(:string2) { 'Fling string while you sing.' }
|
8
|
+
|
9
|
+
context 'without arguments' do
|
10
|
+
describe '#new' do
|
11
|
+
it 'initializes cleanly' do
|
12
|
+
expect { TweetCompressor::Tweet.new }.to_not raise_error
|
13
|
+
expect { TweetCompressor::Tweet.new }.to_not raise_error ArgumentError
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#compressed' do
|
18
|
+
it 'returns empty string' do
|
19
|
+
subject.compressed.should == ''
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#abbr' do
|
25
|
+
it 'abbreviates "JavaScript"' do
|
26
|
+
tweet = TweetCompressor::Tweet.new 'JavaScript should be shortened to JS.'
|
27
|
+
tweet.send :abbr
|
28
|
+
tweet.compressed.should == 'JS should be shortened to JS.'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'abbreviates "string"' do
|
32
|
+
tweet = TweetCompressor::Tweet.new(string2)
|
33
|
+
tweet.send :abbr
|
34
|
+
tweet.compressed.should == 'Fling str while you sing.'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'matches lowercase' do
|
38
|
+
tweet = TweetCompressor::Tweet.new 'javascript should be shortened to js.'
|
39
|
+
tweet.send :abbr
|
40
|
+
tweet.compressed.should == 'JS should be shortened to js.'
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'matches uppercase' do
|
44
|
+
tweet = TweetCompressor::Tweet.new 'JAVASCRIPT SHOULD BE SHORTENED TO JS.'
|
45
|
+
tweet.send :abbr
|
46
|
+
tweet.compressed.should == 'JS SHOULD BE SHORTENED TO JS.'
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'skips hash tags' do
|
50
|
+
text = '#string #JavaScript #string'
|
51
|
+
tweet = TweetCompressor::Tweet.new text
|
52
|
+
tweet.send :abbr
|
53
|
+
tweet.compressed.should == text
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'abbreviates numbers' do
|
57
|
+
text = 'one two three fifteen twenty'
|
58
|
+
tweet = TweetCompressor::Tweet.new text
|
59
|
+
tweet.send :abbr
|
60
|
+
tweet.compressed.should == '1 2 3 15 20'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#apostrophes' do
|
65
|
+
it 'removes apostrophes from contractions' do
|
66
|
+
tweet = TweetCompressor::Tweet.new %q{It's not; I won't, you can't. So don't.}
|
67
|
+
tweet.send :apostrophes
|
68
|
+
tweet.compressed.should == %q{It's not; I wont, you cant. So dont.}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#char_count' do
|
73
|
+
it 'reports an accurate string length' do
|
74
|
+
tweet = TweetCompressor::Tweet.new string1
|
75
|
+
tweet.send(:char_count).should == string1.length
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'pretends URLs are exactly 20 chars' do
|
79
|
+
url = 'http://www.example.com/1234567890' # 33 chars
|
80
|
+
text = "abc #{url} def" # 41 chars (8 + url)
|
81
|
+
tweet = TweetCompressor::Tweet.new text
|
82
|
+
tweet.instance_variable_set :@urls, Array(url)
|
83
|
+
tweet.send(:char_count).should == 28
|
84
|
+
end
|
85
|
+
|
86
|
+
# Short URLs still take up 20 characters on Twitter.
|
87
|
+
it 'handles short urls < 20 chars' do
|
88
|
+
url = 'http://123' # 10 chars
|
89
|
+
text = "abc #{url} def" # 18 chars
|
90
|
+
tweet = TweetCompressor::Tweet.new text
|
91
|
+
tweet.instance_variable_set :@urls, [url]
|
92
|
+
tweet.send(:char_count).should == 28
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#compress' do
|
97
|
+
it "skips strings less than #{TweetCompressor::Tweet::MAX_LENGTH} chars" do
|
98
|
+
tweet = TweetCompressor::Tweet.new string1
|
99
|
+
tweet.compress
|
100
|
+
tweet.compressed.should == string1
|
101
|
+
end
|
102
|
+
|
103
|
+
it "compresses strings above #{TweetCompressor::Tweet::MAX_LENGTH} chars" do
|
104
|
+
text = "%s %s %s" % [string1, string2, filler.downcase]
|
105
|
+
tweet = TweetCompressor::Tweet.new text
|
106
|
+
tweet.compress
|
107
|
+
tweet.compressed.should == 'Smthng wckd ths way cms. Flng str whl you sng. x'
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'stores a compressed copy of the tweet' do
|
111
|
+
tweet = TweetCompressor::Tweet.new(string1 + filler.downcase)
|
112
|
+
tweet.compress
|
113
|
+
tweet.compressed.should_not == tweet.original
|
114
|
+
tweet.original.length.should be > tweet.compressed.length
|
115
|
+
tweet.compressed.length.should == 25
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '#compression_level' do
|
120
|
+
before do
|
121
|
+
@tweet = TweetCompressor::Tweet.new string2 + filler.downcase
|
122
|
+
@tweet.compress
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'returns a Float' do
|
126
|
+
@tweet.compression_level.should be_a Float
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'calculates correctly' do
|
130
|
+
@tweet.compression_level.should == 86.9
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe '#contractions' do
|
135
|
+
it 'contracts words' do
|
136
|
+
text = %q{It is; it is not. I will; I will not. I would not.}
|
137
|
+
tweet = TweetCompressor::Tweet.new text
|
138
|
+
tweet.send :contractions
|
139
|
+
tweet.compressed.should == %q{It's; it's not. I'll; I'll not. I'd not.}
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'preserves case of initial letter' do
|
143
|
+
text = %q{It does not. Is not. Does not. Do not. You must not.}
|
144
|
+
tweet = TweetCompressor::Tweet.new text
|
145
|
+
tweet.send :contractions
|
146
|
+
tweet.compressed.should ==
|
147
|
+
%q{It doesn't. Isn't. Doesn't. Don't. You musn't.}
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#dedupe_consonants' do
|
152
|
+
let(:consonants) { 'LLC BBC CCID' }
|
153
|
+
|
154
|
+
it 'ignores uppercase consonants' do
|
155
|
+
tweet = TweetCompressor::Tweet.new consonants
|
156
|
+
tweet.send :dedupe_consonants
|
157
|
+
tweet.compressed.should == tweet.original
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'leaves one consonant' do
|
161
|
+
tweet = TweetCompressor::Tweet.new consonants.downcase
|
162
|
+
tweet.send :dedupe_consonants
|
163
|
+
tweet.compressed.should == 'lc bc cid'
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe '#dedupe_punct' do
|
168
|
+
let(:punctuation) { '!!! ... ,,, ?! .!' }
|
169
|
+
let(:exceptions ) { 'Foo! Bar...baz. Quux?!' }
|
170
|
+
|
171
|
+
it 'singularizes punctuation' do
|
172
|
+
tweet = TweetCompressor::Tweet.new punctuation
|
173
|
+
tweet.send :dedupe_punct
|
174
|
+
tweet.compressed.should == '! ... , ?! .!'
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'makes exceptions for dashes and ellipses' do
|
178
|
+
tweet = TweetCompressor::Tweet.new exceptions
|
179
|
+
tweet.send :dedupe_punct
|
180
|
+
tweet.compressed.should == exceptions
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
describe '#ing' do
|
186
|
+
it 'shortens sleeping' do
|
187
|
+
TweetCompressor::Tweet.new('sleeping').send(:ing).should == 'sleepg'
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'ignores #sleeping' do
|
191
|
+
TweetCompressor::Tweet.new('#sleeping').send(:ing).should == '#sleeping'
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'ignored excepted words' do
|
195
|
+
TweetCompressor::Tweet.new('fling').send(:ing).should == 'fling'
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe '#remove_vowels' do
|
200
|
+
it 'ignores starting vowels' do
|
201
|
+
TweetCompressor::Tweet.new('aboard').send(:remove_vowels).should == 'abrd'
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'removes internal vowels' do
|
205
|
+
TweetCompressor::Tweet.new('boardwalk').
|
206
|
+
send(:remove_vowels).should == 'brdwlk'
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe '#sentences' do
|
211
|
+
it 'removes space between sentences' do
|
212
|
+
text = '1 2 3. 4 5 6, 7 8 9! 0'
|
213
|
+
tweet = TweetCompressor::Tweet.new text
|
214
|
+
tweet.send :sentences
|
215
|
+
tweet.compressed.should == '1 2 3.4 5 6,7 8 9!0'
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
describe '#texting' do
|
220
|
+
it 'expresses equality' do
|
221
|
+
input = 'foo is a bar. bar is an afoo. baz is the quux'
|
222
|
+
output = 'foo = bar. bar = afoo. baz = quux'
|
223
|
+
tweet = TweetCompressor::Tweet.new input
|
224
|
+
tweet.send :texting
|
225
|
+
tweet.compressed.should == output
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'uses "re" sensibly' do
|
229
|
+
text = '1 about 2. 3 related to 4'
|
230
|
+
tweet = TweetCompressor::Tweet.new text
|
231
|
+
tweet.send :texting
|
232
|
+
tweet.compressed.should == '1 re 2. 3 re 4'
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'strips colons from retweets' do
|
236
|
+
text = 'Foo bar. RT @_baz_quux_: More fubar.'
|
237
|
+
tweet = TweetCompressor::Tweet.new text
|
238
|
+
tweet.send :texting
|
239
|
+
tweet.compressed.should == 'Foo bar. RT @_baz_quux_ More fubar.'
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe '#url_preserve' do
|
244
|
+
let(:url1) { 'http://123' }
|
245
|
+
let(:url2) { 'http://456' }
|
246
|
+
let(:text) { "abc #{url1} def #{url2}" }
|
247
|
+
|
248
|
+
it 'inserts placeholders in tweet' do
|
249
|
+
tweet = TweetCompressor::Tweet.new text
|
250
|
+
tweet.send :url_preserve
|
251
|
+
tweet.compressed.should ==
|
252
|
+
"abc #{Compress::URL_HOLDER} def #{Compress::URL_HOLDER}"
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'stores the URLs' do
|
256
|
+
tweet = TweetCompressor::Tweet.new text
|
257
|
+
tweet.send :url_preserve
|
258
|
+
tweet.urls.should == [url1, url2]
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
describe '#url_restore' do
|
263
|
+
let(:url1) { 'http://123' }
|
264
|
+
let(:url2) { 'http://456' }
|
265
|
+
let(:text) { "abc #{Compress::URL_HOLDER} def #{Compress::URL_HOLDER}" }
|
266
|
+
|
267
|
+
it 'restores URLs to tweet' do
|
268
|
+
tweet = TweetCompressor::Tweet.new text
|
269
|
+
tweet.instance_variable_set :@urls, [url1, url2]
|
270
|
+
tweet.send :url_restore
|
271
|
+
tweet.compressed.should == "abc #{url1} def #{url2}"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require File.join File.basename(Dir.pwd), 'version'
|
5
|
+
|
6
|
+
description = <<'EOF'
|
7
|
+
Compress tweets using a variety of common substitutions in order to maximize
|
8
|
+
room for hashtags, comments on retweets, or just to fit as much information as
|
9
|
+
possible into a single tweet without compromising clarity.
|
10
|
+
EOF
|
11
|
+
|
12
|
+
Gem::Specification.new do |gem|
|
13
|
+
gem.license = 'GPL-3'
|
14
|
+
gem.name = File.basename(Dir.pwd)
|
15
|
+
gem.version = TweetCompressor::VERSION
|
16
|
+
gem.authors = [`git config user.name` ]
|
17
|
+
gem.email = [`git config user.email`]
|
18
|
+
gem.description = description
|
19
|
+
gem.summary = %q{Compress tweets to less than 140 characters.}
|
20
|
+
gem.homepage = "https://github.com/CodeGnome/#{gem.name}"
|
21
|
+
|
22
|
+
gem.files = `git ls-files`.split($/)
|
23
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
24
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
25
|
+
gem.require_paths = %w[lib]
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tweet_compressor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.8.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- |
|
9
|
+
Todd A. Jacobs
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2013-01-28 00:00:00.000000000 Z
|
14
|
+
dependencies: []
|
15
|
+
description: |
|
16
|
+
Compress tweets using a variety of common substitutions in order to maximize
|
17
|
+
room for hashtags, comments on retweets, or just to fit as much information as
|
18
|
+
possible into a single tweet without compromising clarity.
|
19
|
+
email:
|
20
|
+
- |
|
21
|
+
github.projects@codegnome.org
|
22
|
+
executables:
|
23
|
+
- tweet_compressor
|
24
|
+
extensions: []
|
25
|
+
extra_rdoc_files: []
|
26
|
+
files:
|
27
|
+
- .gitignore
|
28
|
+
- .rspec
|
29
|
+
- .ruby-version
|
30
|
+
- AUTHORS
|
31
|
+
- Gemfile
|
32
|
+
- Gemfile.lock
|
33
|
+
- Guardfile
|
34
|
+
- LICENSE
|
35
|
+
- README.md
|
36
|
+
- Rakefile
|
37
|
+
- bin/tweet_compressor
|
38
|
+
- lib/tweet_compressor.rb
|
39
|
+
- lib/tweet_compressor/compress.rb
|
40
|
+
- lib/tweet_compressor/tweet.rb
|
41
|
+
- lib/tweet_compressor/version.rb
|
42
|
+
- spec/spec_helper.rb
|
43
|
+
- spec/tweet_compressor_spec.rb
|
44
|
+
- tweet_compressor.gemspec
|
45
|
+
homepage: https://github.com/CodeGnome/tweet_compressor
|
46
|
+
licenses:
|
47
|
+
- GPL-3
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ! '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
hash: 3765488085706655891
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
requirements: []
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.8.24
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Compress tweets to less than 140 characters.
|
73
|
+
test_files:
|
74
|
+
- spec/spec_helper.rb
|
75
|
+
- spec/tweet_compressor_spec.rb
|