acts_as_markup_on 1.0.0

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.
@@ -0,0 +1,16 @@
1
+ class BlueClothText < BlueCloth
2
+ include Stringlike
3
+
4
+ def initialize(string, options = BlueCloth::DEFAULT_OPTIONS)
5
+ @string = string
6
+ super
7
+ end
8
+
9
+ def to_s
10
+ @string
11
+ end
12
+
13
+ def blank?
14
+ @string.blank?
15
+ end
16
+ end
@@ -0,0 +1,70 @@
1
+ require 'maruku'
2
+
3
+ class Maruku
4
+ include Stringlike
5
+
6
+ attr_reader :text
7
+
8
+ def initialize(s=nil, meta={})
9
+ super(nil)
10
+ self.attributes.merge! meta
11
+ if s
12
+ @text = s
13
+ parse_doc(s)
14
+ end
15
+ end
16
+
17
+ # Used to get the original Markdown text.
18
+ def to_s
19
+ @text
20
+ end
21
+
22
+ # used to be compatable with Rails/ActiveSupport
23
+ def blank?
24
+ @text.blank?
25
+ end
26
+
27
+ end
28
+
29
+ class String
30
+ alias_method :to_html, :to_s
31
+
32
+ def to_xml
33
+ REXML::Text.new(self)
34
+ end
35
+ end
36
+
37
+ module MaRuKu # :nodoc:
38
+ module Out # :nodoc:
39
+ module HTML
40
+
41
+ # We patch this method to play nicely with our own modifications of String.
42
+ #
43
+ # It originally used a +to_html+ method on String we've swapped this out for a +to_xml+
44
+ # method because we need +to_html+ to return the original text on plain text fields of
45
+ # the variable language option on +acts_as_markup_on+
46
+ def array_to_html(array)
47
+ elements = []
48
+ array.each do |item|
49
+ method = item.kind_of?(MDElement) ? "to_html_#{item.node_type}" : "to_xml"
50
+ unless item.respond_to?(method)
51
+ next
52
+ end
53
+
54
+ html_text = item.send(method)
55
+ if html_text.nil?
56
+ raise "Nil html created by method #{method}:\n#{html_text.inspect}\n for object #{item.inspect[0,300]}"
57
+ end
58
+
59
+ if html_text.kind_of?Array
60
+ elements = elements + html_text
61
+ else
62
+ elements << html_text
63
+ end
64
+ end
65
+ elements
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1 @@
1
+ Object.send :alias_method, :to_html, :to_s
@@ -0,0 +1,10 @@
1
+ require 'peg_markdown'
2
+
3
+ class PEGMarkdown
4
+ include Stringlike
5
+
6
+ # used to be compatable with Rails/ActiveSupport
7
+ def blank?
8
+ self.text.blank?
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ require 'rdiscount'
2
+
3
+ class RDiscount
4
+ include Stringlike
5
+
6
+ # Used to get the original Markdown text.
7
+ def to_s
8
+ self.text
9
+ end
10
+
11
+ # used to be compatable with Rails/ActiveSupport
12
+ def blank?
13
+ self.text.blank?
14
+ end
15
+ end
@@ -0,0 +1,100 @@
1
+ require 'rdoc'
2
+
3
+ class RDocWithHyperlinkToHtml < RDoc::Markup::ToHtml
4
+
5
+ # Generate a hyperlink for url, labeled with text. Handle the
6
+ # special cases for img: and link: described under handle_special_HYPEDLINK
7
+ #
8
+ def gen_url(url, text)
9
+ if url =~ /([A-Za-z]+):(.*)/
10
+ type = $1
11
+ path = $2
12
+ else
13
+ type = "http"
14
+ path = url
15
+ url = "http://#{url}"
16
+ end
17
+
18
+ if type == "link"
19
+ if path[0,1] == '#' # is this meaningful?
20
+ url = path
21
+ else
22
+ url = HTMLGenerator.gen_url(@from_path, path)
23
+ end
24
+ end
25
+
26
+ if (type == "http" || type == "link") && url =~ /\.(gif|png|jpg|jpeg|bmp)$/
27
+ "<img src=\"#{url}\" />"
28
+ else
29
+ "<a href=\"#{url}\">#{text.sub(%r{^#{type}:/*}, '')}</a>"
30
+ end
31
+ end
32
+
33
+ # And we're invoked with a potential external hyperlink mailto:
34
+ # just gets inserted. http: links are checked to see if they
35
+ # reference an image. If so, that image gets inserted using an
36
+ # <img> tag. Otherwise a conventional <a href> is used. We also
37
+ # support a special type of hyperlink, link:, which is a reference
38
+ # to a local file whose path is relative to the --op directory.
39
+ #
40
+ def handle_special_HYPERLINK(special)
41
+ url = special.text
42
+ gen_url(url, url)
43
+ end
44
+
45
+ # Here's a hypedlink where the label is different to the URL
46
+ # <label>[url]
47
+ #
48
+ def handle_special_TIDYLINK(special)
49
+ text = special.text
50
+ unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/
51
+ return text
52
+ end
53
+ label = $1
54
+ url = $2
55
+ gen_url(url, label)
56
+ end
57
+
58
+ end
59
+
60
+ # This allows a us to create a wrapper object similar to those provided by the
61
+ # Markdown and Textile libraries. It stores the original and formated HTML text
62
+ # in instance variables. It also stores the SimpleMarkup parser objects in
63
+ # instance variables.
64
+ #
65
+ class RDocText < String
66
+ attr_reader :text
67
+ attr_reader :html
68
+ attr_reader :markup
69
+ attr_reader :html_formater
70
+
71
+ def initialize(str)
72
+ super(str)
73
+ @text = str.to_s
74
+ @markup = RDoc::Markup.new
75
+
76
+ # external hyperlinks
77
+ @markup.add_special(/((link:|https?:|mailto:|ftp:|www\.)\S+\w)/, :HYPERLINK)
78
+
79
+ # and links of the form <text>[<url>]
80
+ @markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\.\S+?\])/, :TIDYLINK)
81
+
82
+ # Convert leading comment markers to spaces, but only
83
+ # if all non-blank lines have them
84
+
85
+ if str =~ /^(?>\s*)[^\#]/
86
+ content = str
87
+ else
88
+ content = str.gsub(/^\s*(#+)/) { $1.tr('#',' ') }
89
+ end
90
+
91
+ @html_formatter = RDocWithHyperlinkToHtml.new(RDoc::Options.new)
92
+
93
+ @html = @markup.convert(@text, @html_formatter)
94
+ end
95
+
96
+ def to_html
97
+ @html
98
+ end
99
+ end
100
+
@@ -0,0 +1,9 @@
1
+ class RedcarpetText < Redcarpet::Markdown
2
+ include Stringlike
3
+
4
+ alias_method :to_s, :text
5
+
6
+ def blank?
7
+ text.blank?
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ require 'wikicloth'
2
+
3
+ class WikiClothText < WikiCloth::Parser
4
+ include Stringlike
5
+
6
+ def initialize(string)
7
+ @text = string
8
+ super({:data => string.to_s})
9
+ end
10
+
11
+ def to_s
12
+ @text.to_s
13
+ end
14
+
15
+ def blank?
16
+ @text.blank?
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ require 'wikitext'
2
+
3
+ # This allows a us to create a wrapper object similar to those provided by the
4
+ # Markdown and Textile libraries. It stores the original and formated HTML text
5
+ # in instance variables.
6
+ #
7
+ class WikitextString < String
8
+ attr_reader :text
9
+ attr_reader :html
10
+
11
+ def initialize(str, *options)
12
+ super(str)
13
+ @text = str.to_s
14
+ @html = Wikitext::Parser.new(*options).parse(@text)
15
+ end
16
+
17
+ def to_html
18
+ @html
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ module ActsAsMarkupOn
2
+ class Railtie < Rails::Railtie
3
+ config.acts_as_markup_on = ActiveSupport::OrderedOptions.new
4
+
5
+ initializer 'acts_as_markup_on.set_config', :after => 'active_record.initialize_database' do |app|
6
+ ActiveSupport.on_load(:acts_as_markup_on) do
7
+ self.markdown_library = app.config.acts_as_markup_on.markdown_library
8
+ self.mediawiki_library = app.config.acts_as_markup_on.mediawiki_library
9
+ end
10
+ end
11
+
12
+ initializer 'acts_as_markup_on.extend_active_record', :after => 'acts_as_markup_on.set_config' do |app|
13
+ ActiveSupport.on_load(:active_record) do
14
+ require 'acts_as_markup_on/exts/object'
15
+ require 'acts_as_markup_on/stringlike'
16
+ require 'acts_as_markup_on/active_record_extension'
17
+ self.send :include, ActsAsMarkupOn::ActiveRecordExtension
18
+ end
19
+ end
20
+
21
+ config.before_configuration do
22
+ config.acts_as_markup_on['markdown_library'] ||= :rdiscount
23
+ config.acts_as_markup_on['mediawiki_library'] ||= :wikicloth
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,7 @@
1
+ # This mixin allows our markup objects (like RDiscount or RedCloth) to have
2
+ # all the normal string methods that are available.
3
+ module Stringlike
4
+ def method_missing(method, *params)
5
+ self.to_s.send(method, *params)
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module ActsAsMarkupOn
2
+ VERSION = '1.0.o'
3
+ end
@@ -0,0 +1,361 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ActsAsMarkdownTest < ActsAsMarkupOnTestCase
4
+ context 'acts_as_markdown_on' do
5
+ setup do
6
+ @markdown_text = '## Markdown Test Text'
7
+ end
8
+
9
+ context 'using RDiscount' do
10
+ setup do
11
+ ActsAsMarkupOn.markdown_library = :rdiscount
12
+ class ::Post < ActiveRecord::Base
13
+ acts_as_markdown_on :body
14
+ end
15
+ @post = Post.create!(:title => 'Blah', :body => @markdown_text)
16
+ end
17
+
18
+ should_act_like_a_string
19
+
20
+ should "have a RDiscount object returned for the column value" do
21
+ assert_kind_of RDiscount, @post.body
22
+ end
23
+
24
+ should "return original markdown text for a `to_s` method call on the column value" do
25
+ assert_equal @markdown_text, @post.body.to_s
26
+ end
27
+
28
+ should 'return false for .blank?' do
29
+ assert !@post.body.blank?
30
+ end
31
+
32
+ should "return formatted html for a `to_html` method call on the column value" do
33
+ assert_match(/<h2(\s\w+\=['"]\w*['"])*\s*>\s*Markdown Test Text\s*<\/h2>/, @post.body.to_html)
34
+ end
35
+
36
+ should "not return escaped html" do
37
+ @post.body = "## Markdown <i>Test</i> Text"
38
+ assert_match(/<i>Test<\/i>/, @post.body.to_html)
39
+ end
40
+
41
+ context "changing value of markdown field should return new markdown object" do
42
+ setup do
43
+ @old_body = @post.body
44
+ @post.body = "`@count = 20`"
45
+ end
46
+
47
+ should "still have an RDiscount object but not the same object" do
48
+ assert_kind_of RDiscount, @post.body
49
+ assert_not_same @post.body, @old_body
50
+ end
51
+
52
+ should "return correct text for `to_s`" do
53
+ assert_equal "`@count = 20`", @post.body.to_s
54
+ end
55
+
56
+ should "return correct HTML for the `to_html` method" do
57
+ assert_match(/<code>\s*\@count\s\=\s20\s*<\/code>/, @post.body.to_html)
58
+ end
59
+
60
+ teardown do
61
+ @old_body = nil
62
+ end
63
+ end
64
+
65
+ teardown do
66
+ @post = nil
67
+ Post.delete_all
68
+ end
69
+ end
70
+
71
+ context 'using RDiscount with options' do
72
+ setup do
73
+ class ::Post
74
+ acts_as_markdown_on :body, :markdown_options => [ :filter_html ]
75
+ end
76
+ @post = Post.new(:title => 'Blah')
77
+ end
78
+
79
+ should "return escaped html because of :filter_html" do
80
+ @post.body = "## Markdown <i>Test</i> Text"
81
+ assert_match(/&lt;i>Test&lt;\/i>/, @post.body.to_html)
82
+ end
83
+ end
84
+
85
+ context 'using Ruby PEG Markdown' do
86
+ setup do
87
+ ActsAsMarkupOn.markdown_library = :rpeg
88
+ class ::Post < ActiveRecord::Base
89
+ acts_as_markdown_on :body
90
+ end
91
+ @post = Post.create!(:title => 'Blah', :body => @markdown_text)
92
+ end
93
+
94
+ should_act_like_a_string
95
+
96
+ should "have a Ruby PEG Markdown object returned for the column value" do
97
+ assert_kind_of PEGMarkdown, @post.body
98
+ end
99
+
100
+ should "return original markdown text for a `to_s` method call on the column value" do
101
+ assert_equal @markdown_text, @post.body.to_s
102
+ end
103
+
104
+ should 'return false for .blank?' do
105
+ assert !@post.body.blank?
106
+ end
107
+
108
+ should "return formated html for a `to_html` method call on the column value" do
109
+ assert_match(/<h2(\s\w+\=['"]\w*['"])*\s*>\s*Markdown Test Text\s*<\/h2>/, @post.body.to_html)
110
+ end
111
+
112
+ should "not return escaped html" do
113
+ @post.body = "## Markdown <i>Test</i> Text"
114
+ assert_match(/<i>Test<\/i>/, @post.body.to_html)
115
+ end
116
+
117
+ context "changing value of markdown field should return new markdown object" do
118
+ setup do
119
+ @old_body = @post.body
120
+ @post.body = "`@count = 20`"
121
+ end
122
+
123
+ should "still have an PEGMarkdown object but not the same object" do
124
+ assert_kind_of PEGMarkdown, @post.body
125
+ assert_not_same @post.body, @old_body
126
+ end
127
+
128
+ should "return correct text for `to_s`" do
129
+ assert_equal "`@count = 20`", @post.body.to_s
130
+ end
131
+
132
+ should "return correct HTML for the `to_html` method" do
133
+ assert_match(/<code>\s*\@count\s\=\s20\s*<\/code>/, @post.body.to_html)
134
+ end
135
+
136
+ teardown do
137
+ @old_body = nil
138
+ end
139
+ end
140
+
141
+ teardown do
142
+ @post = nil
143
+ Post.delete_all
144
+ end
145
+ end
146
+
147
+ context 'using Ruby PEG Markdown with options' do
148
+ setup do
149
+ class ::Post
150
+ acts_as_markdown_on :body, :markdown_options => [ :filter_html ]
151
+ end
152
+ @post = Post.new(:title => 'Blah')
153
+ end
154
+
155
+ should "return no html because of :filter_html" do
156
+ @post.body = "## Markdown <i>Test</i> Text"
157
+ assert_match(/Markdown Test Text/, @post.body.to_html)
158
+ end
159
+ end
160
+
161
+ context 'using BlueCloth' do
162
+ setup do
163
+ ActsAsMarkupOn.markdown_library = :bluecloth
164
+ class ::Post < ActiveRecord::Base
165
+ acts_as_markdown_on :body
166
+ end
167
+ @post = Post.create!(:title => 'Blah', :body => @markdown_text)
168
+ end
169
+
170
+ should_act_like_a_string
171
+
172
+ should "have a BlueCloth object returned for the column value" do
173
+ assert_kind_of BlueCloth, @post.body
174
+ end
175
+
176
+ should "return original markdown text for a `to_s` method call on the column value" do
177
+ assert_equal @markdown_text, @post.body.to_s
178
+ end
179
+
180
+ should 'return false for .blank?' do
181
+ assert !@post.body.blank?
182
+ end
183
+
184
+ should "return formated html for a `to_html` method call on the column value" do
185
+ assert_match(/<h2(\s\w+\=['"]\w*['"])*\s*>\s*Markdown Test Text\s*<\/h2>/, @post.body.to_html)
186
+ end
187
+
188
+ should "not return escaped html" do
189
+ @post.body = "## Markdown <i>Test</i> Text"
190
+ assert_match(/<i>Test<\/i>/, @post.body.to_html)
191
+ end
192
+
193
+ context "changing value of markdown field should return new markdown object" do
194
+ setup do
195
+ @old_body = @post.body
196
+ @post.body = "`@count = 20`"
197
+ end
198
+
199
+ should "still have an BlueCloth object but not the same object" do
200
+ assert_kind_of BlueCloth, @post.body
201
+ assert_not_same @post.body, @old_body
202
+ end
203
+
204
+ should "return correct text for `to_s`" do
205
+ assert_equal "`@count = 20`", @post.body.to_s
206
+ end
207
+
208
+ should "return correct HTML for the `to_html` method" do
209
+ assert_match(/<code>\s*\@count\s\=\s20\s*<\/code>/, @post.body.to_html)
210
+ end
211
+
212
+ teardown do
213
+ @old_body = nil
214
+ end
215
+ end
216
+
217
+ teardown do
218
+ @post = nil
219
+ Post.delete_all
220
+ end
221
+ end
222
+
223
+ context 'using BlueCloth with options' do
224
+ setup do
225
+ class ::Post
226
+ acts_as_markdown_on :body, :markdown_options => [{:escape_html => true}]
227
+ end
228
+ @post = Post.new(:title => 'Blah')
229
+ end
230
+
231
+ # TODO: This test is broken because BleuCloth's behavior is broken.
232
+ should "return escaped html because of :escape_html" do
233
+ @post.body = "## Markdown <i>Test</i> Text"
234
+ assert_match(/&lt;i&gt;Test&lt;\/i&gt;/, @post.body.to_html)
235
+ end
236
+ end
237
+
238
+ context 'using Maruku' do
239
+ setup do
240
+ ActsAsMarkupOn.markdown_library = :maruku
241
+ class ::Post < ActiveRecord::Base
242
+ acts_as_markdown_on :body
243
+ end
244
+ @post = Post.create!(:title => 'Blah', :body => @markdown_text)
245
+ end
246
+
247
+ should_act_like_a_string
248
+
249
+ should "have a Maruku object returned for the column value" do
250
+ assert_kind_of Maruku, @post.body
251
+ end
252
+
253
+ should "return original markdown text for a `to_s` method call on the column value" do
254
+ assert_equal @markdown_text, @post.body.to_s
255
+ end
256
+
257
+ should 'return false for .blank?' do
258
+ assert !@post.body.blank?
259
+ end
260
+
261
+ should "return formated html for a `to_html` method call on the column value" do
262
+ assert_match(/<h2(\s\w+\=['"]\w*['"])*\s*>\s*Markdown Test Text\s*<\/h2>/, @post.body.to_html)
263
+ end
264
+
265
+ context "changing value of markdown field should return new markdown object" do
266
+ setup do
267
+ @old_body = @post.body
268
+ @post.body = "`@count = 20`"
269
+ end
270
+
271
+ should "still have an Maruku object but not the same object" do
272
+ assert_kind_of Maruku, @post.body
273
+ assert_not_same @post.body, @old_body
274
+ end
275
+
276
+ should "return correct text for `to_s`" do
277
+ assert_equal "`@count = 20`", @post.body.to_s
278
+ end
279
+
280
+ should "return correct HTML for the `to_html` method" do
281
+ assert_match(/<code>\s*\@count\s\=\s20\s*<\/code>/, @post.body.to_html)
282
+ end
283
+
284
+ teardown do
285
+ @old_body = nil
286
+ end
287
+ end
288
+
289
+ teardown do
290
+ @post = nil
291
+ Post.delete_all
292
+ end
293
+ end
294
+
295
+ context 'using Redcarpet' do
296
+ setup do
297
+ ActsAsMarkupOn.markdown_library = :redcarpet
298
+ class ::Post < ActiveRecord::Base
299
+ acts_as_markdown_on :body
300
+ end
301
+ @post = Post.create!(:title => 'Blah', :body => @markdown_text)
302
+ end
303
+
304
+ should_act_like_a_string
305
+
306
+ should "have a Redcarpet object returned for the column value" do
307
+ assert_kind_of Redcarpet, @post.body
308
+ end
309
+
310
+ should "return original markdown text for a `to_s` method call on the column value" do
311
+ assert_equal @markdown_text, @post.body.to_s
312
+ end
313
+
314
+ should 'return false for .blank?' do
315
+ assert !@post.body.blank?
316
+ end
317
+
318
+ should "return formatted html for a `to_html` method call on the column value" do
319
+ assert_match(/<h2(\s\w+\=['"]\w*['"])*\s*>\s*Markdown Test Text\s*<\/h2>/, @post.body.to_html)
320
+ end
321
+
322
+ should "not return escaped html" do
323
+ @post.body = "## Markdown <i>Test</i> Text"
324
+ assert_match(/<i>Test<\/i>/, @post.body.to_html)
325
+ end
326
+
327
+ context "changing value of markdown field should return new markdown object" do
328
+ setup do
329
+ @old_body = @post.body
330
+ @post.body = "`@count = 20`"
331
+ end
332
+
333
+ should "still have an Redcarpet object but not the same object" do
334
+ assert_kind_of Redcarpet, @post.body
335
+ assert_not_same @post.body, @old_body
336
+ end
337
+
338
+ should "return correct text for `to_s`" do
339
+ assert_equal "`@count = 20`", @post.body.to_s
340
+ end
341
+
342
+ should "return correct HTML for the `to_html` method" do
343
+ assert_match(/<code>\s*\@count\s\=\s20\s*<\/code>/, @post.body.to_html)
344
+ end
345
+
346
+ teardown do
347
+ @old_body = nil
348
+ end
349
+ end
350
+
351
+ teardown do
352
+ @post = nil
353
+ Post.delete_all
354
+ end
355
+ end
356
+
357
+ teardown do
358
+ @markdown_text = nil
359
+ end
360
+ end
361
+ end