usertext 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +14 -0
- data/Gemfile.lock +47 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/usertext.rb +223 -0
- data/test/helper.rb +18 -0
- data/test/test_usertext.rb +233 -0
- metadata +150 -0
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "shoulda", ">= 0"
|
10
|
+
gem "bundler", "~> 1.0.0"
|
11
|
+
gem "jeweler", "~> 1.5.2"
|
12
|
+
gem "rcov", ">= 0"
|
13
|
+
gem "actionpack"
|
14
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
abstract (1.0.0)
|
5
|
+
actionpack (3.0.3)
|
6
|
+
activemodel (= 3.0.3)
|
7
|
+
activesupport (= 3.0.3)
|
8
|
+
builder (~> 2.1.2)
|
9
|
+
erubis (~> 2.6.6)
|
10
|
+
i18n (~> 0.4)
|
11
|
+
rack (~> 1.2.1)
|
12
|
+
rack-mount (~> 0.6.13)
|
13
|
+
rack-test (~> 0.5.6)
|
14
|
+
tzinfo (~> 0.3.23)
|
15
|
+
activemodel (3.0.3)
|
16
|
+
activesupport (= 3.0.3)
|
17
|
+
builder (~> 2.1.2)
|
18
|
+
i18n (~> 0.4)
|
19
|
+
activesupport (3.0.3)
|
20
|
+
builder (2.1.2)
|
21
|
+
erubis (2.6.6)
|
22
|
+
abstract (>= 1.0.0)
|
23
|
+
git (1.2.5)
|
24
|
+
i18n (0.4.2)
|
25
|
+
jeweler (1.5.2)
|
26
|
+
bundler (~> 1.0.0)
|
27
|
+
git (>= 1.2.5)
|
28
|
+
rake
|
29
|
+
rack (1.2.1)
|
30
|
+
rack-mount (0.6.13)
|
31
|
+
rack (>= 1.0.0)
|
32
|
+
rack-test (0.5.7)
|
33
|
+
rack (>= 1.0)
|
34
|
+
rake (0.8.7)
|
35
|
+
rcov (0.9.9)
|
36
|
+
shoulda (2.11.3)
|
37
|
+
tzinfo (0.3.24)
|
38
|
+
|
39
|
+
PLATFORMS
|
40
|
+
ruby
|
41
|
+
|
42
|
+
DEPENDENCIES
|
43
|
+
actionpack
|
44
|
+
bundler (~> 1.0.0)
|
45
|
+
jeweler (~> 1.5.2)
|
46
|
+
rcov
|
47
|
+
shoulda
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Frankie Roberto
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= usertext
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Contributing to usertext
|
6
|
+
|
7
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
8
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
9
|
+
* Fork the project
|
10
|
+
* Start a feature/bugfix branch
|
11
|
+
* Commit and push until you are happy with your contribution
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2011 Frankie Roberto. See LICENSE.txt for
|
18
|
+
further details.
|
19
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
+
gem.name = "usertext"
|
16
|
+
gem.homepage = "http://github.com/frankieroberto/usertext"
|
17
|
+
gem.license = "MIT"
|
18
|
+
gem.summary = %Q{A simple text processing engine for user-contributed text.}
|
19
|
+
gem.description = %Q{Not a markup language - rather, an library for processing user-contributed text that handles the common ways in which ordinary users add meaning, structure and formatting using plain text.}
|
20
|
+
gem.email = "frankie@frankieroberto.com"
|
21
|
+
gem.authors = ["Frankie Roberto"]
|
22
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
23
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
24
|
+
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
25
|
+
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
26
|
+
end
|
27
|
+
Jeweler::RubygemsDotOrgTasks.new
|
28
|
+
|
29
|
+
require 'rake/testtask'
|
30
|
+
Rake::TestTask.new(:test) do |test|
|
31
|
+
test.libs << 'lib' << 'test'
|
32
|
+
test.pattern = 'test/**/test_*.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
|
36
|
+
require 'rcov/rcovtask'
|
37
|
+
Rcov::RcovTask.new do |test|
|
38
|
+
test.libs << 'test'
|
39
|
+
test.pattern = 'test/**/test_*.rb'
|
40
|
+
test.verbose = true
|
41
|
+
end
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
48
|
+
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "usertext #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/usertext.rb
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
class Usertext
|
2
|
+
|
3
|
+
|
4
|
+
def initialize(text)
|
5
|
+
@string = text
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_html
|
9
|
+
html = @string
|
10
|
+
|
11
|
+
html = html.to_s
|
12
|
+
html = cleanup_newlines(html)
|
13
|
+
|
14
|
+
# Character level markup
|
15
|
+
html = replace_typography(html)
|
16
|
+
html = insert_currency_symbols(html)
|
17
|
+
html = insert_fraction_symbols(html)
|
18
|
+
html = insert_roman_numerals(html)
|
19
|
+
html = insert_smileys(html)
|
20
|
+
html = insert_copyright_symbols(html)
|
21
|
+
|
22
|
+
# Block level markup
|
23
|
+
html = html_escape(html)
|
24
|
+
html = mark_code(html)
|
25
|
+
html = auto_link(html)
|
26
|
+
html = auto_link_phone_numbers(html)
|
27
|
+
html = block_element_markup(html)
|
28
|
+
|
29
|
+
return html
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def block_element_markup(text)
|
35
|
+
new_text = Array.new
|
36
|
+
li_re = /^\*\s(.*)$/
|
37
|
+
ol_re = /^\d+[\.\)]\s(.*)$/
|
38
|
+
quote_re = /^“(.*)”$/
|
39
|
+
code_re = /^<code>.*<\/code>$/
|
40
|
+
text.split("\n\n").map do |block|
|
41
|
+
case block
|
42
|
+
when li_re
|
43
|
+
lines = block.gsub(li_re, '<li>\1</li>')
|
44
|
+
content_tag("ul", "\n" + lines + "\n")
|
45
|
+
when ol_re
|
46
|
+
lines = block.gsub(ol_re, '<li>\1</li>')
|
47
|
+
content_tag("ol", "\n" + lines + "\n")
|
48
|
+
when quote_re
|
49
|
+
content_tag("blockquote", content_tag("p", block.gsub(quote_re, '\1')))
|
50
|
+
when code_re
|
51
|
+
content_tag("div", block)
|
52
|
+
else
|
53
|
+
content_tag("p", block)
|
54
|
+
end
|
55
|
+
end .join("\n\n")
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
def replace_typography(string)
|
60
|
+
string.
|
61
|
+
gsub(/\'(\d\ds)/, '’\1'). # replacing '30s with ’30s
|
62
|
+
gsub(/(\d+)'(\s)/, '\1′\2'). # replacing ' with single prime
|
63
|
+
gsub(/(\d+)"(\s)/, '\1″\2'). # replacing " with double prime
|
64
|
+
gsub(/(\d+)'''(\s)/, '\1‴\2'). # replacing ''' with triple prime
|
65
|
+
gsub(/(\d+)""(\s)/, '\1⁗\2'). # replacing "" with quadruple prime
|
66
|
+
gsub(/([^\s]+)\'(\s)/, '\1’\2'). # replacing ' with ’ (right single quote)
|
67
|
+
gsub(/(\s)\'([^\s])/, '\1‘\2'). # replacing ' with ‘ (left single quote)
|
68
|
+
gsub(/([^\s]+)\"/, '\1”'). # replacing " with ” (right double quote)
|
69
|
+
gsub(/\"([a-zA-Z])/, '“\1'). # replacing " with “ (left double quote)
|
70
|
+
gsub(/([^\s])\'([^\s])/, '\1’\2'). # replacing ' with ’ (apostrophe)
|
71
|
+
# gsub(/(\s)\"(\s)/, '\1〃\2'). # replacing " with 〃 (ditto mark)
|
72
|
+
gsub(/(\d+)x(\d+)/, '\1×\2'). # replacing x with multiplication char
|
73
|
+
gsub(/(\d{3,})-(\d{3,})/, '\1‒\2'). # replacing dash with figure dash
|
74
|
+
gsub(/(\d)-(\d)/, '\1–\2'). # replacing hypen-dash with en dash (for ranges)
|
75
|
+
gsub(/([A-Za-z\d])--([A-Za-z\d])/, '\1—\2'). # replacing double hypen-dash with em dash (parenthetical thought)
|
76
|
+
gsub(/([a-zA-Z])-([\sa-zA-Z])/, '\1‐\2'). # replacing hyphen-dash with hyphen char
|
77
|
+
gsub(/([\d])-([\d])/, '\1–\2'). # replacing - with en-dash
|
78
|
+
gsub(/([^\.])\.\.\.([^\.]|$)/, '\1…\2').# replacing ... with elipsis
|
79
|
+
gsub(/(\d) degrees c/, '\1℃'). # inserting typographic degrees character
|
80
|
+
gsub(/(\d) degrees f/, '\1℉'). # inserting typographic degrees character
|
81
|
+
gsub(/(\d) degrees (f)/, '\1°\2'). # inserting typographic degrees character
|
82
|
+
gsub(/(\s|^)No.(\s\d|$)/, '\1№\2'). # replace No. 3 with № 3
|
83
|
+
gsub(/(\s|\A)c\/o(\s|$)/, '\1℅\2'). # replace c/o with ℅
|
84
|
+
gsub(/(\s|\A)a\/c(\s[A-Z]|$)/, '\1℀\2'). # replace a/c with ℀
|
85
|
+
|
86
|
+
|
87
|
+
to_s
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
def insert_fraction_symbols(text)
|
92
|
+
text.
|
93
|
+
gsub(/(\s|^)1\/4(\s|$)/, '\1¼\2'). # replacing 1/4 with ¼
|
94
|
+
gsub(/(\s|^)1\/2(\s|$)/, '\1½\2'). # replacing 1/2 with ½
|
95
|
+
gsub(/(\s|^)3\/4(\s|$)/, '\1¾\2'). # replacing 3/4 with ¾
|
96
|
+
gsub(/(\s|^)1\/3(\s|$)/, '\1⅓\2'). # replacing 1/3 with ⅓
|
97
|
+
gsub(/(\s|^)2\/3(\s|$)/, '\1⅔\2'). # replacing 2/3 with ⅔
|
98
|
+
gsub(/(\s|^)1\/5(\s|$)/, '\1⅕\2'). # replacing 1/5 with ⅕
|
99
|
+
gsub(/(\s|^)2\/5(\s|$)/, '\1⅖\2'). # replacing 2/5 with ⅖
|
100
|
+
gsub(/(\s|^)4\/5(\s|$)/, '\1⅖\2'). # replacing 4/5 with ⅘
|
101
|
+
gsub(/(\s|^)1\/6(\s|$)/, '\1⅙\2'). # replacing 1/6 with ⅙
|
102
|
+
gsub(/(\s|^)5\/6(\s|$)/, '\1⅖\2'). # replacing 5/6 with ⅚
|
103
|
+
gsub(/(\s|^)1\/8(\s|$)/, '\1⅛\2'). # replacing 1/8 with ⅛
|
104
|
+
gsub(/(\s|^)3\/8(\s|$)/, '\1⅜\2'). # replacing 3/8 with ⅜
|
105
|
+
gsub(/(\s|^)5\/8(\s|$)/, '\1⅝\2'). # replacing 5/8 with ⅝
|
106
|
+
gsub(/(\s|^)7\/8(\s|$)/, '\1⅞\2'). # replacing 7/8 with ⅞
|
107
|
+
to_s
|
108
|
+
end
|
109
|
+
|
110
|
+
def insert_currency_symbols(text)
|
111
|
+
text.
|
112
|
+
gsub(/(\s|^)GBP(\d+)/, '\1£\2'). # inserting Pound sign.
|
113
|
+
gsub(/(\s|^)USD?(\d+)/, '\1$\2'). # inserting Dollar sign.
|
114
|
+
gsub(/(\s|^)EUR(\d+)/, '\1€\2'). # inserting Euro sign.
|
115
|
+
gsub(/(\s|^)YEN(\d+)/, '\1¥\2'). # inserting Yen sign.
|
116
|
+
gsub(/(\s|^)ILS(\d+)/, '\1₪\2'). # inserting Israeli shekel symbol.
|
117
|
+
gsub(/(\s|^)GEL(\d+)/, '\1ლ\2'). # inserting Georgian lari symbol.
|
118
|
+
gsub(/(\s|^)AFN(\d+)/, '\1؋\2'). # inserting Afghan afghani symbol.
|
119
|
+
gsub(/(\s|^)ALL(\d+)/, '\1L\2'). # inserting Albanian lek symbol.
|
120
|
+
gsub(/(\s|^)DZD(\d+)/, '\1د.ج\2'). # inserting Algerian dinar symbol.
|
121
|
+
gsub(/(\s|^)PHP(\d+)/, '\1₱\2'). # inserting Philippine peso symbol.
|
122
|
+
gsub(/(\s|^)UAH(\d+)/, '\1₴\2'). # inserting Ukrainian hryvnia symbol.
|
123
|
+
to_s
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
def cleanup_newlines(text)
|
128
|
+
text.gsub(/\r\n?/, "\n") # \r\n and \r -> \n
|
129
|
+
end
|
130
|
+
|
131
|
+
def auto_link_phone_numbers(text)
|
132
|
+
text.gsub(/(\s|^)((0|\+44)\d{10,10})\b/) do
|
133
|
+
text = $1 + "<a href=\"tel:" + $2 + "\">" + $2 + "</a>"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def mark_code(text)
|
138
|
+
text.
|
139
|
+
gsub(/(^<[a-zA-Z]+.*$|<[a-zA-Z]+.*>)/) do
|
140
|
+
"<code>" + $1 + "</code>"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def auto_link(text)
|
145
|
+
auto_link_urls(text)
|
146
|
+
end
|
147
|
+
|
148
|
+
def auto_link_urls(text)
|
149
|
+
|
150
|
+
auto_link_re = %r{
|
151
|
+
( # leading text
|
152
|
+
<\w+.*?>| # leading HTML tag, or
|
153
|
+
[^=!:'"/]| # leading punctuation, or
|
154
|
+
^ # beginning of line
|
155
|
+
)
|
156
|
+
(https?://|ftp://) # protocol spec
|
157
|
+
|
158
|
+
(
|
159
|
+
[-\w]+ # subdomain or domain
|
160
|
+
(?:\.[-\w]+)* # remaining subdomains or domain
|
161
|
+
(?::\d+)? # port
|
162
|
+
(?:/(?:(?:[~\w\+@%-]|(?:[,.;:][^\s$]))+)?)* # path
|
163
|
+
(?:\?[\w\+@%&=.;-]+)? # query string
|
164
|
+
(?:\#[\w\-\/]*)? # trailing anchor
|
165
|
+
)(([[:punct:]]|\s|<|$)) # trailing text
|
166
|
+
}x
|
167
|
+
|
168
|
+
text.gsub(auto_link_re) do
|
169
|
+
all, a, b, c, d = $&, $1, $2, $3, $5
|
170
|
+
|
171
|
+
text = a + "<a href=\"" + b + c + "\">" + truncate_in_middle(c, 40) + "</a>" + $5
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# This helper is like the trunctate() method included in Rails core, but truncates
|
176
|
+
# in the middle of the string rather than at the end. This is useful for things like
|
177
|
+
# URLs, which it is sometimes helpful to show the beginning and the end.
|
178
|
+
def truncate_in_middle(text, length = 30, truncate_string = "...")
|
179
|
+
if text
|
180
|
+
l = (length - truncate_string.length) / 2
|
181
|
+
return text if length > text.length
|
182
|
+
return text[0...l] + truncate_string + text[-l..-1]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def insert_roman_numerals(text)
|
187
|
+
text.
|
188
|
+
gsub(/(\s|^)II([\s\.]|$)/, '\1Ⅱ\2'). # Replace II with Ⅱ (roman numeral)
|
189
|
+
gsub(/(\s|^)III([\s\.]|$)/, '\1Ⅲ\2'). # Replace III with Ⅲ (roman numeral)
|
190
|
+
gsub(/(\s|^)IV([\s\.]|$)/, '\1Ⅳ\2'). # Replace IV with Ⅳ (roman numeral)
|
191
|
+
gsub(/(\s|^)V([\s\.]|$)/, '\1Ⅴ\2'). # Replace V with Ⅴ (roman numeral)
|
192
|
+
gsub(/(\s|^)VI([\s\.]|$)/, '\1Ⅵ\2'). # Replace VI with Ⅵ (roman numeral)
|
193
|
+
gsub(/(\s|^)VII([\s\.]|$)/, '\1Ⅶ\2'). # Replace VII with Ⅶ (roman numeral)
|
194
|
+
gsub(/(\s|^)VIII([\s\.]|$)/, '\1Ⅷ\2'). # Replace VIII with Ⅷ (roman numeral)
|
195
|
+
gsub(/(\s|^)IX([\s\.]|$)/, '\1Ⅸ\2'). # Replace IX with Ⅸ (roman numeral)
|
196
|
+
gsub(/(\s|^)X([\s\.]|$)/, '\1Ⅹ\2'). # Replace X with Ⅹ (roman numeral)
|
197
|
+
to_s
|
198
|
+
end
|
199
|
+
|
200
|
+
def insert_smileys(text)
|
201
|
+
text.
|
202
|
+
gsub(/(\s|^):-?\)(\s|$)/, '\1☺\2'). # Replace :-) or :) with ☺
|
203
|
+
gsub(/(\s|^):-?\((\s|$)/, '\1☹\2'). # Replace :-( or :( with ☹
|
204
|
+
to_s
|
205
|
+
end
|
206
|
+
|
207
|
+
def insert_copyright_symbols(text)
|
208
|
+
text.
|
209
|
+
gsub(/\(R\)([\W]|$)/, 'Ⓡ\1'). # inserting Registered trademark sign.
|
210
|
+
gsub(/\(c\)([\sA-Za-z]|$)/, '©\1'). # inserting Copyright sign.
|
211
|
+
to_s
|
212
|
+
end
|
213
|
+
|
214
|
+
def content_tag(tagname, contents, options = {})
|
215
|
+
"<" + tagname + ">" + contents + "</" + tagname + ">"
|
216
|
+
end
|
217
|
+
|
218
|
+
def html_escape(s)
|
219
|
+
s.to_s.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/</, "<")
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
+
require 'usertext'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|
@@ -0,0 +1,233 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestUsertext < Test::Unit::TestCase
|
4
|
+
|
5
|
+
should "test that the gem has been loaded okay" do
|
6
|
+
|
7
|
+
assert_equal "", Usertext.new("").to_html
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
should "Insert paragraph tags" do
|
12
|
+
assert_equal("<p>Hello!</p>", Usertext.new("Hello!").to_html)
|
13
|
+
end
|
14
|
+
|
15
|
+
should "Insert two paragraph tags" do
|
16
|
+
assert_equal("<p>Hello!</p>\n\n<p>Wow!</p>", Usertext.new("Hello!\n\nWow!").to_html)
|
17
|
+
end
|
18
|
+
|
19
|
+
should "Insert three paragraph tags" do
|
20
|
+
assert_equal("<p>Hello!</p>\n\n<p>Wow!</p>\n\n<p>Woop!</p>",
|
21
|
+
Usertext.new("Hello!\n\nWow!\n\nWoop!").to_html)
|
22
|
+
end
|
23
|
+
|
24
|
+
should "Insert four paragraph tags" do
|
25
|
+
assert_equal("<p>Hello!</p>\n\n<p>Wow!</p>\n\n<p>Woop!</p>\n\n<p>Pow!</p>",
|
26
|
+
Usertext.new("Hello!\n\nWow!\n\nWoop!\n\nPow!").to_html)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_elipsis_insertion
|
30
|
+
assert_equal "<p>I eat… worms!</p>", Usertext.new("I eat... worms!").to_html
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_elipsis_insertion_at_end_of_string
|
34
|
+
assert_equal "<p>I want to…</p>", Usertext.new("I want to...").to_html
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_insert_typographic_apostrophe
|
38
|
+
assert_equal "<p>Jamie’s house</p>", Usertext.new("Jamie's house").to_html
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_insert_typographic_apostrophe_in_decade_reference
|
42
|
+
assert_equal "<p>It was acceptable in the ’80s.</p>", Usertext.new("It was acceptable in the '80s.").to_html
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_insert_typographic_double_quotes
|
46
|
+
assert_equal "<p>She said “hello”.</p>", Usertext.new("She said \"hello\".").to_html
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_insert_typographic_single_quotes
|
50
|
+
assert_equal "<p>She said ‘hello’.</p>", Usertext.new("She said 'hello'.").to_html
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_insert_multiplication_character
|
54
|
+
assert_equal "<p>2×2=4</p>", Usertext.new("2x2=4").to_html
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_insert_figure_dash
|
58
|
+
assert_equal "<p>Telephone 867‒5309.</p>", Usertext.new("Telephone 867-5309.").to_html
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_insert_en_dash
|
62
|
+
assert_equal "<p>For ages 3–5.</p>", Usertext.new("For ages 3-5.").to_html
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_insert_em_dash
|
66
|
+
assert_equal "<p>I am not sure—although I really should be—what to do.</p>", Usertext.new("I am not sure--although I really should be--what to do.").to_html
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
def test_insert_degrees_symbol
|
72
|
+
assert_equal "<p>It is 20℃.</p>", Usertext.new("It is 20 degrees c.").to_html
|
73
|
+
assert_equal "<p>It is 20℉.</p>", Usertext.new("It is 20 degrees f.").to_html
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_insert_pound_symbol
|
77
|
+
assert_equal "<p>That costs £30.</p>", Usertext.new("That costs GBP30.").to_html
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_insert_dollar_symbol
|
81
|
+
assert_equal "<p>That costs $30.</p>", Usertext.new("That costs USD30.").to_html
|
82
|
+
assert_equal "<p>That costs $30.</p>", Usertext.new("That costs US30.").to_html
|
83
|
+
assert_equal "<p>Item code PTSTUSD7201.</p>", Usertext.new("Item code PTSTUSD7201.").to_html
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_insert_euro_symbol
|
87
|
+
assert_equal "<p>That costs €30.</p>", Usertext.new("That costs EUR30.").to_html
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_insert_yen_symbol
|
91
|
+
assert_equal "<p>That costs ¥30.</p>", Usertext.new("That costs YEN30.").to_html
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_insert_sheqel_sign_symbol
|
95
|
+
assert_equal "<p>That costs ₪30.</p>", Usertext.new("That costs ILS30.").to_html
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
def test_insert_copyright_symbol
|
100
|
+
assert_equal "<p>©Frankie Roberto</p>", Usertext.new("(c)Frankie Roberto").to_html
|
101
|
+
assert_equal "<p>© Frankie Roberto</p>", Usertext.new("(c) Frankie Roberto").to_html
|
102
|
+
assert_equal "<p>This text is in ©</p>", Usertext.new("This text is in (c)").to_html
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
def test_insert_suspended_hyphen
|
107
|
+
assert_equal "<p>nineteenth‐ and twentieth‐century writers</p>", Usertext.new("nineteenth- and twentieth-century writers").to_html
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_insert_hyphen
|
111
|
+
assert_equal "<p>This is a real‐world example.</p>", Usertext.new("This is a real-world example.").to_html
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_auto_link_phone_numbers
|
115
|
+
assert_equal "<p>Phone me on <a href=\"tel:+447736111111\">+447736111111</a></p>", Usertext.new("Phone me on +447736111111").to_html
|
116
|
+
assert_equal "<p>Phone me on <a href=\"tel:+447736111111\">+447736111111</a>.</p>", Usertext.new("Phone me on +447736111111.").to_html
|
117
|
+
assert_equal "<p>Phone me on <a href=\"tel:07736111111\">07736111111</a></p>", Usertext.new("Phone me on 07736111111").to_html
|
118
|
+
assert_equal "<p>Phone me on <a href=\"tel:07736111111\">07736111111</a>.</p>", Usertext.new("Phone me on 07736111111.").to_html
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_insert_numero_character
|
122
|
+
assert_equal "<p>I live at № 4 Privet Drive</p>", Usertext.new("I live at No. 4 Privet Drive").to_html
|
123
|
+
assert_equal "<p>Tell me your №</p>", Usertext.new("Tell me your No.").to_html
|
124
|
+
assert_equal "<p>№ 3 is the winner!</p>", Usertext.new("No. 3 is the winner!").to_html
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_care_of_character
|
128
|
+
assert_equal "<p>Send it to me ℅ my company.</p>", Usertext.new("Send it to me c/o my company.").to_html
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
def test_code_tag
|
133
|
+
assert_equal "<p>Don’t use the <code><blink></code> tag.</p>", Usertext.new("Don't use the <blink> tag.").to_html
|
134
|
+
assert_equal "<p>4 < 7 > 1</p>", Usertext.new("4 < 7 > 1").to_html
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_block_of_code
|
138
|
+
assert_equal "<p>Use this code:</p>\n\n<div><code><html></code></div>",
|
139
|
+
Usertext.new("Use this code:\n\n<html>").to_html
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_mark_list
|
143
|
+
assert_equal "<ul>\n<li>Milk</li>\n<li>Eggs</li>\n<li>Flour</li>\n</ul>", Usertext.new("* Milk\n* Eggs\n* Flour").to_html
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_mark_lists
|
147
|
+
assert_equal "<p>List:</p>\n\n<ul>\n<li>apples</li>\n<li>pears</li>\n</ul>\n\n<p>And forget milk!</p>", Usertext.new("List:\n\n* apples\n* pears\n\nAnd forget milk!").to_html
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_mark_lists_2
|
151
|
+
assert_equal "<p>List:</p>\n\n<ul>\n<li>apples</li>\n<li>pears</li>\n</ul>", Usertext.new("List:\n\n* apples\n* pears").to_html
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_mark_ordered_list
|
155
|
+
assert_equal "<p>Method:</p>\n\n<ol>\n<li>Stir</li>\n<li>Bake</li>\n<li>Lick spoon</li>\n</ol>", Usertext.new("Method:\n\n1. Stir\n2. Bake\n3. Lick spoon").to_html
|
156
|
+
assert_equal "<p>Method:</p>\n\n<ol>\n<li>Stir</li>\n<li>Bake</li>\n<li>Lick spoon</li>\n</ol>", Usertext.new("Method:\n\n1) Stir\n2) Bake\n3) Lick spoon").to_html
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_nothing
|
160
|
+
assert_equal("", Usertext.new("").to_html)
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_auto_link_ftp_url
|
164
|
+
assert_equal "<p><a href=\"ftp://test.com\">test.com</a></p>", Usertext.new("ftp://test.com").to_html
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_auto_link_url
|
168
|
+
assert_equal "<p><a href=\"http://test.com\">test.com</a></p>", Usertext.new("http://test.com").to_html
|
169
|
+
end
|
170
|
+
|
171
|
+
def test_auto_link_truncated_url
|
172
|
+
assert_equal "<p><a href=\"http://thisisareallyreallyreallyreallyreallylongurl.com\">thisisareallyreall...yreallylongurl.com</a></p>", Usertext.new("http://thisisareallyreallyreallyreallyreallylongurl.com").to_html
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_one_quarter_symbol
|
176
|
+
assert_equal "<p>I have ¼ hour left.</p>",
|
177
|
+
Usertext.new("I have 1/4 hour left.").to_html
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_one_half_symbol
|
181
|
+
assert_equal "<p>I have ½ hour left.</p>",
|
182
|
+
Usertext.new("I have 1/2 hour left.").to_html
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_threw_quarters_symbol
|
186
|
+
assert_equal "<p>I have ¾ hour left.</p>", Usertext.new("I have 3/4 hour left.").to_html
|
187
|
+
assert_equal "<p>Give me ¾</p>", Usertext.new("Give me 3/4").to_html
|
188
|
+
assert_equal "<p>I am on 123/4567.</p>", Usertext.new("I am on 123/4567.").to_html
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_insert_registered_trademark_symbol
|
192
|
+
assert_equal "<p>I like LegoⓇ.</p>", Usertext.new("I like Lego(R).").to_html
|
193
|
+
assert_equal "<p>I like LegoⓇ</p>", Usertext.new("I like Lego(R)").to_html
|
194
|
+
assert_equal "<p>I like LegoⓇ bricks.</p>", Usertext.new("I like Lego(R) bricks.").to_html
|
195
|
+
assert_equal "<p>x = 2(R)n</p>", Usertext.new("x = 2(R)n").to_html
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
def test_blockquote
|
200
|
+
assert_equal "<p>She said:</p>\n\n<blockquote><p>I love you.</p></blockquote>", Usertext.new("She said:\n\n\"I love you.\"").to_html
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
def test_insert_roman_numerals
|
205
|
+
assert_equal "<p>The year Ⅱ.</p>", Usertext.new("The year II.").to_html
|
206
|
+
assert_equal "<p>Ⅱ green bottles.</p>", Usertext.new("II green bottles.").to_html
|
207
|
+
assert_equal "<p>The year Ⅲ.</p>", Usertext.new("The year III.").to_html
|
208
|
+
assert_equal "<p>Ⅲ green bottles.</p>", Usertext.new("III green bottles.").to_html
|
209
|
+
assert_equal "<p>The year Ⅳ.</p>", Usertext.new("The year IV.").to_html
|
210
|
+
assert_equal "<p>Ⅳ green bottles.</p>", Usertext.new("IV green bottles.").to_html
|
211
|
+
assert_equal "<p>The year Ⅴ.</p>", Usertext.new("The year V.").to_html
|
212
|
+
assert_equal "<p>Ⅴ green bottles.</p>", Usertext.new("V green bottles.").to_html
|
213
|
+
assert_equal "<p>The year Ⅵ.</p>", Usertext.new("The year VI.").to_html
|
214
|
+
assert_equal "<p>Ⅵ green bottles.</p>", Usertext.new("VI green bottles.").to_html
|
215
|
+
assert_equal "<p>The year Ⅶ.</p>", Usertext.new("The year VII.").to_html
|
216
|
+
assert_equal "<p>Ⅶ green bottles.</p>", Usertext.new("VII green bottles.").to_html
|
217
|
+
assert_equal "<p>The year Ⅷ.</p>", Usertext.new("The year VIII.").to_html
|
218
|
+
assert_equal "<p>Ⅷ green bottles.</p>", Usertext.new("VIII green bottles.").to_html
|
219
|
+
assert_equal "<p>The year Ⅸ.</p>", Usertext.new("The year IX.").to_html
|
220
|
+
assert_equal "<p>Ⅸ green bottles.</p>", Usertext.new("IX green bottles.").to_html
|
221
|
+
assert_equal "<p>The year Ⅹ.</p>", Usertext.new("The year X.").to_html
|
222
|
+
assert_equal "<p>Ⅹ green bottles.</p>", Usertext.new("X green bottles.").to_html
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_insert_smiley_characters
|
226
|
+
assert_equal "<p>Yay! ☺</p>", Usertext.new("Yay! :-)").to_html
|
227
|
+
assert_equal "<p>Yay! ☺</p>", Usertext.new("Yay! :)").to_html
|
228
|
+
assert_equal "<p>No! ☹</p>", Usertext.new("No! :-(").to_html
|
229
|
+
assert_equal "<p>No! ☹</p>", Usertext.new("No! :(").to_html
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
end
|
metadata
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: usertext
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Frankie Roberto
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-03-06 00:00:00 +00:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 3
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :development
|
32
|
+
name: shoulda
|
33
|
+
prerelease: false
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
hash: 23
|
42
|
+
segments:
|
43
|
+
- 1
|
44
|
+
- 0
|
45
|
+
- 0
|
46
|
+
version: 1.0.0
|
47
|
+
type: :development
|
48
|
+
name: bundler
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ~>
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 7
|
58
|
+
segments:
|
59
|
+
- 1
|
60
|
+
- 5
|
61
|
+
- 2
|
62
|
+
version: 1.5.2
|
63
|
+
type: :development
|
64
|
+
name: jeweler
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
type: :development
|
78
|
+
name: rcov
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: *id004
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
91
|
+
type: :development
|
92
|
+
name: actionpack
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: *id005
|
95
|
+
description: Not a markup language - rather, an library for processing user-contributed text that handles the common ways in which ordinary users add meaning, structure and formatting using plain text.
|
96
|
+
email: frankie@frankieroberto.com
|
97
|
+
executables: []
|
98
|
+
|
99
|
+
extensions: []
|
100
|
+
|
101
|
+
extra_rdoc_files:
|
102
|
+
- LICENSE.txt
|
103
|
+
- README.rdoc
|
104
|
+
files:
|
105
|
+
- Gemfile
|
106
|
+
- Gemfile.lock
|
107
|
+
- LICENSE.txt
|
108
|
+
- README.rdoc
|
109
|
+
- Rakefile
|
110
|
+
- VERSION
|
111
|
+
- lib/usertext.rb
|
112
|
+
- test/helper.rb
|
113
|
+
- test/test_usertext.rb
|
114
|
+
has_rdoc: true
|
115
|
+
homepage: http://github.com/frankieroberto/usertext
|
116
|
+
licenses:
|
117
|
+
- MIT
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
|
121
|
+
require_paths:
|
122
|
+
- lib
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
hash: 3
|
129
|
+
segments:
|
130
|
+
- 0
|
131
|
+
version: "0"
|
132
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
none: false
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
hash: 3
|
138
|
+
segments:
|
139
|
+
- 0
|
140
|
+
version: "0"
|
141
|
+
requirements: []
|
142
|
+
|
143
|
+
rubyforge_project:
|
144
|
+
rubygems_version: 1.3.7
|
145
|
+
signing_key:
|
146
|
+
specification_version: 3
|
147
|
+
summary: A simple text processing engine for user-contributed text.
|
148
|
+
test_files:
|
149
|
+
- test/helper.rb
|
150
|
+
- test/test_usertext.rb
|