acts_as_markup_extended 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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+
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,101 @@
1
+ require 'rdoc/markup/simple_markup'
2
+ require 'rdoc/markup/simple_markup/to_html'
3
+
4
+ class RDocWithHyperlinkToHtml < SM::ToHtml
5
+
6
+ # Generate a hyperlink for url, labeled with text. Handle the
7
+ # special cases for img: and link: described under handle_special_HYPEDLINK
8
+ #
9
+ def gen_url(url, text)
10
+ if url =~ /([A-Za-z]+):(.*)/
11
+ type = $1
12
+ path = $2
13
+ else
14
+ type = "http"
15
+ path = url
16
+ url = "http://#{url}"
17
+ end
18
+
19
+ if type == "link"
20
+ if path[0,1] == '#' # is this meaningful?
21
+ url = path
22
+ else
23
+ url = HTMLGenerator.gen_url(@from_path, path)
24
+ end
25
+ end
26
+
27
+ if (type == "http" || type == "link") && url =~ /\.(gif|png|jpg|jpeg|bmp)$/
28
+ "<img src=\"#{url}\" />"
29
+ else
30
+ "<a href=\"#{url}\">#{text.sub(%r{^#{type}:/*}, '')}</a>"
31
+ end
32
+ end
33
+
34
+ # And we're invoked with a potential external hyperlink mailto:
35
+ # just gets inserted. http: links are checked to see if they
36
+ # reference an image. If so, that image gets inserted using an
37
+ # <img> tag. Otherwise a conventional <a href> is used. We also
38
+ # support a special type of hyperlink, link:, which is a reference
39
+ # to a local file whose path is relative to the --op directory.
40
+ #
41
+ def handle_special_HYPERLINK(special)
42
+ url = special.text
43
+ gen_url(url, url)
44
+ end
45
+
46
+ # Here's a hypedlink where the label is different to the URL
47
+ # <label>[url]
48
+ #
49
+ def handle_special_TIDYLINK(special)
50
+ text = special.text
51
+ unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/
52
+ return text
53
+ end
54
+ label = $1
55
+ url = $2
56
+ gen_url(url, label)
57
+ end
58
+
59
+ end
60
+
61
+ # This allows a us to create a wrapper object similar to those provided by the
62
+ # Markdown and Textile libraries. It stores the original and formated HTML text
63
+ # in instance variables. It also stores the SimpleMarkup parser objects in
64
+ # instance variables.
65
+ #
66
+ class RDocText < String
67
+ attr_reader :text
68
+ attr_reader :html
69
+ attr_reader :markup
70
+ attr_reader :html_formater
71
+
72
+ def initialize(str)
73
+ super(str)
74
+ @text = str.to_s
75
+ @markup = SM::SimpleMarkup.new
76
+
77
+ # external hyperlinks
78
+ @markup.add_special(/((link:|https?:|mailto:|ftp:|www\.)\S+\w)/, :HYPERLINK)
79
+
80
+ # and links of the form <text>[<url>]
81
+ @markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\.\S+?\])/, :TIDYLINK)
82
+
83
+ # Convert leading comment markers to spaces, but only
84
+ # if all non-blank lines have them
85
+
86
+ if str =~ /^(?>\s*)[^\#]/
87
+ content = str
88
+ else
89
+ content = str.gsub(/^\s*(#+)/) { $1.tr('#',' ') }
90
+ end
91
+
92
+ @html_formatter = RDocWithHyperlinkToHtml.new
93
+
94
+ @html = @markup.convert(@text, @html_formatter)
95
+ end
96
+
97
+ def to_html
98
+ @html
99
+ end
100
+ end
101
+
@@ -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,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,79 @@
1
+ require 'set'
2
+ require 'active_support'
3
+ require 'active_support/core_ext'
4
+
5
+ module ActsAsMarkup
6
+ # :stopdoc:
7
+ VERSION = '1.3.4'.freeze
8
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
9
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
10
+ # :startdoc:
11
+
12
+ # This exception is raised when an unsupported markup language is supplied to acts_as_markup.
13
+ class UnsupportedMarkupLanguage < ArgumentError
14
+ end
15
+ # This exception is raised when an unsupported Markdown library is set to the config value.
16
+ class UnsportedMarkdownLibrary < ArgumentError
17
+ end
18
+ # this extension is raised when an extension method doesn't exist
19
+ class UnknownExtensionMethod < ArgumentError
20
+ end
21
+ DEFAULT_MARKDOWN_LIB = :rdiscount
22
+
23
+ MARKDOWN_LIBS = { :rdiscount => {:class_name => "RDiscount",
24
+ :lib_name => "rdiscount"},
25
+ :bluecloth => {:class_name => "BlueCloth",
26
+ :lib_name => "bluecloth"},
27
+ :rpeg => {:class_name => "PEGMarkdown",
28
+ :lib_name => "peg_markdown"},
29
+ :maruku => {:class_name => "Maruku",
30
+ :lib_name => "maruku"} }
31
+
32
+ LIBRARY_EXTENSIONS = ::Set.new(Dir[ActsAsMarkup::LIBPATH + 'acts_as_markup/exts/*.rb'].map {|file| File.basename(file, '.rb')}).delete('string')
33
+
34
+ @@markdown_library = DEFAULT_MARKDOWN_LIB
35
+ mattr_accessor :markdown_library
36
+
37
+ # :stopdoc:
38
+ # Returns the version string for the library.
39
+ #
40
+ def self.version
41
+ VERSION
42
+ end
43
+
44
+ # Returns the library path for the module. If any arguments are given,
45
+ # they will be joined to the end of the library path using
46
+ # <tt>File.join</tt>.
47
+ #
48
+ def self.libpath( *args )
49
+ args.empty? ? LIBPATH : ::File.join(LIBPATH, *args)
50
+ end
51
+
52
+ # Returns the path for the module. If any arguments are given,
53
+ # they will be joined to the end of the path using
54
+ # <tt>File.join</tt>.
55
+ #
56
+ def self.path( *args )
57
+ args.empty? ? PATH : ::File.join(PATH, *args)
58
+ end
59
+
60
+ # Utility method used to rquire all files ending in .rb that lie in the
61
+ # directory below this file that has the same name as the filename passed
62
+ # in. Optionally, a specific _directory_ name can be passed in such that
63
+ # the _filename_ does not have to be equivalent to the directory.
64
+ #
65
+ def self.require_all_libs_relative_to( fname, dir = nil )
66
+ dir ||= ::File.basename(fname, '.*')
67
+ search_me = ::File.expand_path(
68
+ ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
69
+
70
+ Dir.glob(search_me).sort.each {|rb| require rb}
71
+ end
72
+ # :startdoc:
73
+
74
+ end # module ActsAsMarkup
75
+
76
+ require 'acts_as_markup/exts/object'
77
+ require 'acts_as_markup/stringlike'
78
+ require 'markup_extensions'
79
+ ActsAsMarkup.require_all_libs_relative_to __FILE__, 'acts'
@@ -0,0 +1,24 @@
1
+ ActsAsMarkup.require_all_libs_relative_to __FILE__, 'markup_methods'
2
+ ActsAsMarkup.require_all_libs_relative_to "lib/.", 'markup_methods'
3
+
4
+ module MarkupExtensions
5
+ class MString < String
6
+ include MarkupExtensionMethods
7
+
8
+ def run_methods(methods)
9
+ (methods == :all ?
10
+ MarkupExtensionMethods.instance_methods :
11
+ methods
12
+ ).inject(self) { |mstring, meth|
13
+ if mstring.respond_to? meth
14
+ MString.new(mstring.send(meth))
15
+ else
16
+ raise ActsAsMarkup::UnknownExtensionMethod,
17
+ "Extension method \"#{meth.to_s}\" is not defined "
18
+ MString.new(mstring)
19
+ end
20
+ }
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ module MarkupExtensionMethods
2
+
3
+ # This sample extension replaces URL strings in the form:
4
+ # "http://..."
5
+ # with links:
6
+ # "<a href="http://..."
7
+ #
8
+ # Strings that are already part of
9
+ # <a href= ...> or <img src= ...>
10
+ # or inside
11
+ # <code> or <pre>
12
+ # tags will remain unchanged
13
+ #
14
+ # (This extension can be used for any markup language.)
15
+ #
16
+ def ahttp
17
+ gsub( /http:\/\/[^\s><"']+/ ) {
18
+ match = $&; before = $`; after = $'
19
+ before !~ /\s+(href|src|)\s*=\s*['"]*$/ &&
20
+ after !~ /^[^<]*<\/a>/ &&
21
+ before !~ /(<code>|<pre>).*$/ ?
22
+ %Q~<a href="#{match}">#{match}</a>~ :
23
+ match
24
+ }
25
+ end
26
+
27
+ end
@@ -0,0 +1,30 @@
1
+ module MarkupExtensionMethods
2
+
3
+ # This sample extension allows list elements to act as a checklist.
4
+ # If the markup list indicator is followed by a disposition character
5
+ # and a space, this method will make checklist substitutions.
6
+ #
7
+ # For example, when this method sees this in a Markdown list:
8
+ # '- x item one'
9
+ # or this in a Textile list:
10
+ # '* x item one"
11
+ # it will substitute:
12
+ # '<li <strong>(x)</strong> item one'.
13
+ #
14
+ # This method recognizes these disposition characters.
15
+ # x - item completed
16
+ # 0 - item dropped
17
+ # d - item deferred
18
+ # @ - item in progress
19
+ #
20
+ # (this extension can be used for any markup language.)
21
+ #
22
+ def checklist
23
+ gsub(/<li>([x0d@]) (\S)/) {
24
+ m1 = $1;m2 = $2
25
+ m1 = ">" if m1 == "d"
26
+ "<li><strong>(#{m1.upcase}) </strong>#{m2}"
27
+ }
28
+ end
29
+
30
+ end
@@ -0,0 +1,27 @@
1
+ module MarkupExtensionMethods
2
+
3
+ # This sample extension inserts a company logo.
4
+ # If Markdown contains:
5
+ # "[logo](home)"
6
+ # or Textile contains:
7
+ # "logo":home
8
+ # The generated HTML contains the company logo and links to the home page.
9
+ #
10
+ # (This extension can be used for any markup language)
11
+ #
12
+ def logo
13
+ gsub( /<a href="home">logo<\/a>/ ) {
14
+ match = $&; before = $`
15
+ if before !~ /(<code>|<pre>).*$/
16
+ %Q~<a href="http://www.google.com">\n~ +
17
+ %Q~<img id="logo" alt="Google"~ +
18
+ %Q~ src="http://www.google.com/images/logos/google_logo.gif"~ +
19
+ %Q~ style="border: 0 none;">\n~ +
20
+ %Q~</a>\n~
21
+ else
22
+ match
23
+ end
24
+ }
25
+ end
26
+
27
+ end
@@ -0,0 +1,298 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ActsAsMarkdownTest < ActsAsMarkupTestCase
4
+ context 'acts_as_markdown' do
5
+ setup do
6
+ @markdown_text = '## Markdown Test Text'
7
+ end
8
+
9
+ context 'using RDiscount' do
10
+ setup do
11
+ ActsAsMarkup.markdown_library = :rdiscount
12
+ class ::Post < ActiveRecord::Base
13
+ acts_as_markdown :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 :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
+ ActsAsMarkup.markdown_library = :rpeg
88
+ class ::Post < ActiveRecord::Base
89
+ acts_as_markdown :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 :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
+ ActsAsMarkup.markdown_library = :bluecloth
164
+ class ::Post < ActiveRecord::Base
165
+ acts_as_markdown :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 :body, :markdown_options => [ :filter_html ]
227
+ end
228
+ @post = Post.new(:title => 'Blah')
229
+ end
230
+
231
+ should "return escaped html because of :filter_html" do
232
+ @post.body = "## Markdown <i>Test</i> Text"
233
+ assert_match(/&lt;i&gt;Test&lt;\/i&gt;/, @post.body.to_html)
234
+ end
235
+ end
236
+
237
+ context 'using Maruku' do
238
+ setup do
239
+ ActsAsMarkup.markdown_library = :maruku
240
+ class ::Post < ActiveRecord::Base
241
+ acts_as_markdown :body
242
+ end
243
+ @post = Post.create!(:title => 'Blah', :body => @markdown_text)
244
+ end
245
+
246
+ should_act_like_a_string
247
+
248
+ should "have a Maruku object returned for the column value" do
249
+ assert_kind_of Maruku, @post.body
250
+ end
251
+
252
+ should "return original markdown text for a `to_s` method call on the column value" do
253
+ assert_equal @markdown_text, @post.body.to_s
254
+ end
255
+
256
+ should 'return false for .blank?' do
257
+ assert !@post.body.blank?
258
+ end
259
+
260
+ should "return formated html for a `to_html` method call on the column value" do
261
+ assert_match(/<h2(\s\w+\=['"]\w*['"])*\s*>\s*Markdown Test Text\s*<\/h2>/, @post.body.to_html)
262
+ end
263
+
264
+ context "changing value of markdown field should return new markdown object" do
265
+ setup do
266
+ @old_body = @post.body
267
+ @post.body = "`@count = 20`"
268
+ end
269
+
270
+ should "still have an Maruku object but not the same object" do
271
+ assert_kind_of Maruku, @post.body
272
+ assert_not_same @post.body, @old_body
273
+ end
274
+
275
+ should "return correct text for `to_s`" do
276
+ assert_equal "`@count = 20`", @post.body.to_s
277
+ end
278
+
279
+ should "return correct HTML for the `to_html` method" do
280
+ assert_match(/<code>\s*\@count\s\=\s20\s*<\/code>/, @post.body.to_html)
281
+ end
282
+
283
+ teardown do
284
+ @old_body = nil
285
+ end
286
+ end
287
+
288
+ teardown do
289
+ @post = nil
290
+ Post.delete_all
291
+ end
292
+ end
293
+
294
+ teardown do
295
+ @markdown_text = nil
296
+ end
297
+ end
298
+ end