usertext 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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&#12291;\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(/(^&lt;[a-zA-Z]+.*$|&lt;[a-zA-Z]+.*&gt;)/) 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(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;")
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>&lt;blink&gt;</code> tag.</p>", Usertext.new("Don't use the <blink> tag.").to_html
134
+ assert_equal "<p>4 &lt; 7 &gt; 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>&lt;html&gt;</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