vkhater-redcarpet 2.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,37 @@
1
+ #ifndef REDCARPET_H__
2
+ #define REDCARPET_H__
3
+
4
+ #define RSTRING_NOT_MODIFIED
5
+ #include "ruby.h"
6
+ #include <stdio.h>
7
+
8
+ #ifdef HAVE_RUBY_ENCODING_H
9
+ # include <ruby/encoding.h>
10
+ # define redcarpet_str_new(data, size, enc) rb_enc_str_new(data, size, enc)
11
+ #else
12
+ # define redcarpet_str_new(data, size, enc) rb_str_new(data, size)
13
+ #endif
14
+
15
+ #include "markdown.h"
16
+ #include "html.h"
17
+
18
+ #define CSTR2SYM(s) (ID2SYM(rb_intern((s))))
19
+
20
+ extern void Init_redcarpet_rndr();
21
+
22
+ struct redcarpet_renderopt {
23
+ struct html_renderopt html;
24
+ VALUE link_attributes;
25
+ VALUE self;
26
+ VALUE base_class;
27
+ #ifdef HAVE_RUBY_ENCODING_H
28
+ rb_encoding *active_enc;
29
+ #endif
30
+ };
31
+
32
+ struct rb_redcarpet_rndr {
33
+ struct sd_callbacks callbacks;
34
+ struct redcarpet_renderopt options;
35
+ };
36
+
37
+ #endif
@@ -0,0 +1,81 @@
1
+ #include "stack.h"
2
+ #include <string.h>
3
+
4
+ int
5
+ stack_grow(struct stack *st, size_t new_size)
6
+ {
7
+ void **new_st;
8
+
9
+ if (st->asize >= new_size)
10
+ return 0;
11
+
12
+ new_st = realloc(st->item, new_size * sizeof(void *));
13
+ if (new_st == NULL)
14
+ return -1;
15
+
16
+ memset(new_st + st->asize, 0x0,
17
+ (new_size - st->asize) * sizeof(void *));
18
+
19
+ st->item = new_st;
20
+ st->asize = new_size;
21
+
22
+ if (st->size > new_size)
23
+ st->size = new_size;
24
+
25
+ return 0;
26
+ }
27
+
28
+ void
29
+ stack_free(struct stack *st)
30
+ {
31
+ if (!st)
32
+ return;
33
+
34
+ free(st->item);
35
+
36
+ st->item = NULL;
37
+ st->size = 0;
38
+ st->asize = 0;
39
+ }
40
+
41
+ int
42
+ stack_init(struct stack *st, size_t initial_size)
43
+ {
44
+ st->item = NULL;
45
+ st->size = 0;
46
+ st->asize = 0;
47
+
48
+ if (!initial_size)
49
+ initial_size = 8;
50
+
51
+ return stack_grow(st, initial_size);
52
+ }
53
+
54
+ void *
55
+ stack_pop(struct stack *st)
56
+ {
57
+ if (!st->size)
58
+ return NULL;
59
+
60
+ return st->item[--st->size];
61
+ }
62
+
63
+ int
64
+ stack_push(struct stack *st, void *item)
65
+ {
66
+ if (stack_grow(st, st->size * 2) < 0)
67
+ return -1;
68
+
69
+ st->item[st->size++] = item;
70
+ return 0;
71
+ }
72
+
73
+ void *
74
+ stack_top(struct stack *st)
75
+ {
76
+ if (!st->size)
77
+ return NULL;
78
+
79
+ return st->item[st->size - 1];
80
+ }
81
+
@@ -0,0 +1,29 @@
1
+ #ifndef STACK_H__
2
+ #define STACK_H__
3
+
4
+ #include <stdlib.h>
5
+
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
10
+ struct stack {
11
+ void **item;
12
+ size_t size;
13
+ size_t asize;
14
+ };
15
+
16
+ void stack_free(struct stack *);
17
+ int stack_grow(struct stack *, size_t);
18
+ int stack_init(struct stack *, size_t);
19
+
20
+ int stack_push(struct stack *, void *);
21
+
22
+ void *stack_pop(struct stack *);
23
+ void *stack_top(struct stack *);
24
+
25
+ #ifdef __cplusplus
26
+ }
27
+ #endif
28
+
29
+ #endif
@@ -0,0 +1,124 @@
1
+ require 'redcarpet.so'
2
+
3
+ module Redcarpet
4
+ VERSION = '2.2.2'
5
+
6
+ class Markdown
7
+ attr_reader :renderer
8
+ end
9
+
10
+ module Render
11
+
12
+ # XHTML Renderer
13
+ class XHTML < HTML
14
+ def initialize(extensions={})
15
+ super(extensions.merge(:xhtml => true))
16
+ end
17
+ end
18
+
19
+ # HTML + SmartyPants renderer
20
+ class SmartyHTML < HTML
21
+ include SmartyPants
22
+ end
23
+
24
+ # SmartyPants Mixin module
25
+ #
26
+ # Implements SmartyPants.postprocess, which
27
+ # performs smartypants replacements on the HTML file,
28
+ # once it has been fully rendered.
29
+ #
30
+ # To add SmartyPants postprocessing to your custom
31
+ # renderers, just mixin the module `include SmartyPants`
32
+ #
33
+ # You can also use this as a standalone SmartyPants
34
+ # implementation.
35
+ #
36
+ # Example:
37
+ #
38
+ # # Mixin
39
+ # class CoolRenderer < HTML
40
+ # include SmartyPants
41
+ # # more code here
42
+ # end
43
+ #
44
+ # # Standalone
45
+ # Redcarpet::Render::SmartyPants.render("you're")
46
+ #
47
+ module SmartyPants
48
+ extend self
49
+ def self.render(text)
50
+ postprocess text
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ # Compatibility class;
57
+ # Creates an instance of Redcarpet with the RedCloth API.
58
+ class RedcarpetCompat
59
+ attr_accessor :text
60
+
61
+ def initialize(text, *exts)
62
+ exts_hash, render_hash = *parse_extensions_and_renderer_options(exts)
63
+ @text = text
64
+ renderer = Redcarpet::Render::HTML.new(render_hash)
65
+ @markdown = Redcarpet::Markdown.new(renderer, exts_hash)
66
+ end
67
+
68
+ def to_html(*_dummy)
69
+ @markdown.render(@text)
70
+ end
71
+
72
+ private
73
+
74
+ EXTENSION_MAP = {
75
+ # old name => new name
76
+ :autolink => :autolink,
77
+ :fenced_code => :fenced_code_blocks,
78
+ :filter_html => :filter_html,
79
+ :hard_wrap => :hard_wrap,
80
+ :lax_htmlblock => :lax_spacing,
81
+ :no_image => :no_images,
82
+ :no_intraemphasis => :no_intra_emphasis,
83
+ :no_links => :no_links,
84
+ :filter_styles => :no_styles,
85
+ :safelink => :safe_links_only,
86
+ :space_header => :space_after_headers,
87
+ :strikethrough => :strikethrough,
88
+ :tables => :tables,
89
+ :generate_toc => :with_toc_data,
90
+ :xhtml => :xhtml,
91
+ # old names with no new mapping
92
+ :gh_blockcode => nil,
93
+ :no_tables => nil,
94
+ :smart => nil,
95
+ :strict => nil
96
+ }
97
+
98
+ RENDERER_OPTIONS = [:filter_html, :no_images, :no_links, :no_styles,
99
+ :safe_links_only, :with_toc_data, :hard_wrap, :xhtml]
100
+
101
+ def rename_extensions(exts)
102
+ exts.map do |old_name|
103
+ if new_name = EXTENSION_MAP[old_name]
104
+ new_name
105
+ else
106
+ old_name
107
+ end
108
+ end.compact
109
+ end
110
+
111
+ # Returns two hashes, the extensions and renderer options
112
+ # given the extension list
113
+ def parse_extensions_and_renderer_options(exts)
114
+ exts = rename_extensions(exts)
115
+ exts.partition {|ext| !RENDERER_OPTIONS.include?(ext) }.
116
+ map {|list| list_to_truthy_hash(list) }
117
+ end
118
+
119
+ # Turns a list of symbols into a hash of <tt>symbol => true</tt>.
120
+ def list_to_truthy_hash(list)
121
+ list.inject({}) {|h, k| h[k] = true; h }
122
+ end
123
+ end
124
+
@@ -0,0 +1,3 @@
1
+ require 'redcarpet'
2
+
3
+ Markdown = RedcarpetCompat unless defined? Markdown
@@ -0,0 +1,65 @@
1
+ module Redcarpet
2
+ module Render
3
+ class ManPage < Base
4
+
5
+ def normal_text(text)
6
+ text.gsub('-', '\\-').strip
7
+ end
8
+
9
+ def block_code(code, language)
10
+ "\n.nf\n#{normal_text(code)}\n.fi\n"
11
+ end
12
+
13
+ def codespan(code)
14
+ block_code(code, nil)
15
+ end
16
+
17
+ def header(title, level)
18
+ case level
19
+ when 1
20
+ "\n.TH #{title}\n"
21
+
22
+ when 2
23
+ "\n.SH #{title}\n"
24
+
25
+ when 3
26
+ "\n.SS #{title}\n"
27
+ end
28
+ end
29
+
30
+ def double_emphasis(text)
31
+ "\\fB#{text}\\fP"
32
+ end
33
+
34
+ def emphasis(text)
35
+ "\\fI#{text}\\fP"
36
+ end
37
+
38
+ def linebreak
39
+ "\n.LP\n"
40
+ end
41
+
42
+ def paragraph(text)
43
+ "\n.TP\n#{text}\n"
44
+ end
45
+
46
+ def list(content, list_type)
47
+ case list_type
48
+ when :ordered
49
+ "\n\n.nr step 0 1\n#{content}\n"
50
+ when :unordered
51
+ "\n.\n#{content}\n"
52
+ end
53
+ end
54
+
55
+ def list_item(content, list_type)
56
+ case list_type
57
+ when :ordered
58
+ ".IP \\n+[step]\n#{content.strip}\n"
59
+ when :unordered
60
+ ".IP \\[bu] 2 \n#{content.strip}\n"
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,33 @@
1
+
2
+ module Redcarpet
3
+ module Render
4
+ # Markdown-stripping renderer. Turns Markdown into plaintext
5
+ # Thanks to @toupeira (Markus Koller)
6
+ class StripDown < Base
7
+ # Methods where the first argument is the text content
8
+ [
9
+ # block-level calls
10
+ :block_code, :block_quote,
11
+ :block_html, :header, :list,
12
+ :list_item, :paragraph,
13
+
14
+ # span-level calls
15
+ :autolink, :codespan, :double_emphasis,
16
+ :emphasis, :raw_html, :triple_emphasis,
17
+ :strikethrough, :superscript,
18
+
19
+ # low level rendering
20
+ :entity, :normal_text
21
+ ].each do |method|
22
+ define_method method do |*args|
23
+ args.first
24
+ end
25
+ end
26
+
27
+ # Other methods where the text content is in another argument
28
+ def link(link, title, content)
29
+ content
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+ Gem::Specification.new do |s|
3
+ s.name = 'vkhater-redcarpet'
4
+ s.version = '2.2.3'
5
+ s.summary = "Markdown that smells nice"
6
+ s.description = 'A fast, safe and extensible Markdown to (X)HTML parser'
7
+ s.date = '2012-10-19'
8
+ s.email = 'vicent@github.com'
9
+ s.homepage = 'http://github.com/vmg/redcarpet'
10
+ s.authors = ["Natacha Porté", "Vicent Martí"]
11
+ # = MANIFEST =
12
+ s.files = %w[
13
+ COPYING
14
+ Gemfile
15
+ Gemfile.lock
16
+ README.markdown
17
+ Rakefile
18
+ bin/redcarpet
19
+ ext/redcarpet/autolink.c
20
+ ext/redcarpet/autolink.h
21
+ ext/redcarpet/buffer.c
22
+ ext/redcarpet/buffer.h
23
+ ext/redcarpet/extconf.rb
24
+ ext/redcarpet/houdini.h
25
+ ext/redcarpet/houdini_href_e.c
26
+ ext/redcarpet/houdini_html_e.c
27
+ ext/redcarpet/html.c
28
+ ext/redcarpet/html.h
29
+ ext/redcarpet/html_blocks.h
30
+ ext/redcarpet/html_smartypants.c
31
+ ext/redcarpet/markdown.c
32
+ ext/redcarpet/markdown.h
33
+ ext/redcarpet/rc_markdown.c
34
+ ext/redcarpet/rc_render.c
35
+ ext/redcarpet/redcarpet.h
36
+ ext/redcarpet/stack.c
37
+ ext/redcarpet/stack.h
38
+ lib/redcarpet.rb
39
+ lib/redcarpet/compat.rb
40
+ lib/redcarpet/render_man.rb
41
+ lib/redcarpet/render_strip.rb
42
+ redcarpet.gemspec
43
+ sundown
44
+ test/redcarpet_test.rb
45
+ ]
46
+ # = MANIFEST =
47
+ s.test_files = ["test/redcarpet_test.rb"]
48
+ s.extra_rdoc_files = ["COPYING"]
49
+ s.extensions = ["ext/redcarpet/extconf.rb"]
50
+ s.executables = ["redcarpet"]
51
+ s.require_paths = ["lib"]
52
+ s.add_development_dependency "nokogiri"
53
+ s.add_development_dependency "rake-compiler"
54
+ end
@@ -0,0 +1,447 @@
1
+ # coding: UTF-8
2
+ rootdir = File.dirname(File.dirname(__FILE__))
3
+ $LOAD_PATH.unshift "#{rootdir}/lib"
4
+
5
+ if defined? Encoding
6
+ Encoding.default_internal = 'UTF-8'
7
+ end
8
+
9
+ require 'test/unit'
10
+ require 'redcarpet'
11
+ require 'redcarpet/render_man'
12
+ require 'nokogiri'
13
+
14
+ def html_equal(html_a, html_b)
15
+ assert_equal Nokogiri::HTML::DocumentFragment.parse(html_a).to_html,
16
+ Nokogiri::HTML::DocumentFragment.parse(html_b).to_html
17
+ end
18
+
19
+ class SmartyPantsTest < Test::Unit::TestCase
20
+ def setup
21
+ @pants = Redcarpet::Render::SmartyPants
22
+ end
23
+
24
+ def test_that_smart_converts_single_quotes_in_words_that_end_in_re
25
+ markdown = @pants.render("<p>They're not for sale.</p>")
26
+ assert_equal "<p>They&rsquo;re not for sale.</p>", markdown
27
+ end
28
+
29
+ def test_that_smart_converts_single_quotes_in_words_that_end_in_ll
30
+ markdown = @pants.render("<p>Well that'll be the day</p>")
31
+ assert_equal "<p>Well that&rsquo;ll be the day</p>", markdown
32
+ end
33
+
34
+ def test_that_smart_converts_double_quotes_to_curly_quotes
35
+ rd = @pants.render(%(<p>"Quoted text"</p>))
36
+ assert_equal %(<p>&ldquo;Quoted text&rdquo;</p>), rd
37
+ end
38
+
39
+ def test_that_smart_gives_ve_suffix_a_rsquo
40
+ rd = @pants.render("<p>I've been meaning to tell you ..</p>")
41
+ assert_equal "<p>I&rsquo;ve been meaning to tell you ..</p>", rd
42
+ end
43
+
44
+ def test_that_smart_gives_m_suffix_a_rsquo
45
+ rd = @pants.render("<p>I'm not kidding</p>")
46
+ assert_equal "<p>I&rsquo;m not kidding</p>", rd
47
+ end
48
+
49
+ def test_that_smart_gives_d_suffix_a_rsquo
50
+ rd = @pants.render("<p>what'd you say?</p>")
51
+ assert_equal "<p>what&rsquo;d you say?</p>", rd
52
+ end
53
+ end
54
+
55
+ class HTMLRenderTest < Test::Unit::TestCase
56
+ def setup
57
+ @markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML)
58
+ @rndr = {
59
+ :no_html => Redcarpet::Render::HTML.new(:filter_html => true),
60
+ :no_images => Redcarpet::Render::HTML.new(:no_images => true),
61
+ :no_links => Redcarpet::Render::HTML.new(:no_links => true),
62
+ :safe_links => Redcarpet::Render::HTML.new(:safe_links_only => true),
63
+ :escape_html => Redcarpet::Render::HTML.new(:escape_html => true),
64
+ :hard_wrap => Redcarpet::Render::HTML.new(:hard_wrap => true),
65
+ }
66
+ end
67
+
68
+ def render_with(rndr, text)
69
+ Redcarpet::Markdown.new(rndr).render(text)
70
+ end
71
+
72
+ # Hint: overrides filter_html, no_images and no_links
73
+ def test_that_escape_html_works
74
+ source = <<EOS
75
+ Through <em>NO</em> <script>DOUBLE NO</script>
76
+
77
+ <script>BAD</script>
78
+
79
+ <img src="/favicon.ico" />
80
+ EOS
81
+ expected = <<EOE
82
+ <p>Through &lt;em&gt;NO&lt;/em&gt; &lt;script&gt;DOUBLE NO&lt;/script&gt;</p>
83
+
84
+ <p>&lt;script&gt;BAD&lt;/script&gt;</p>
85
+
86
+ <p>&lt;img src=&quot;/favicon.ico&quot; /&gt;
87
+
88
+ EOE
89
+
90
+ markdown = render_with(@rndr[:escape_html], source)
91
+ html_equal expected, markdown
92
+ end
93
+
94
+ def test_that_filter_html_works
95
+ markdown = render_with(@rndr[:no_html], 'Through <em>NO</em> <script>DOUBLE NO</script>')
96
+ html_equal "<p>Through NO DOUBLE NO</p>", markdown
97
+ end
98
+
99
+ def test_filter_html_doesnt_break_two_space_hard_break
100
+ markdown = render_with(@rndr[:no_html], "Lorem, \nipsum\n")
101
+ html_equal "<p>Lorem,<br/>\nipsum</p>\n", markdown
102
+ end
103
+
104
+ def test_that_no_image_flag_works
105
+ rd = render_with(@rndr[:no_images], %(![dust mite](http://dust.mite/image.png) <img src="image.png" />))
106
+ assert rd !~ /<img/
107
+ end
108
+
109
+ def test_that_no_links_flag_works
110
+ rd = render_with(@rndr[:no_links], %([This link](http://example.net/) <a href="links.html">links</a>))
111
+ assert rd !~ /<a /
112
+ end
113
+
114
+ def test_that_safelink_flag_works
115
+ rd = render_with(@rndr[:safe_links], "[IRC](irc://chat.freenode.org/#freenode)")
116
+ html_equal "<p>[IRC](irc://chat.freenode.org/#freenode)</p>\n", rd
117
+ end
118
+
119
+ def test_that_hard_wrap_works
120
+ rd = render_with(@rndr[:hard_wrap], <<EOE)
121
+ Hello world,
122
+ this is just a simple test
123
+
124
+ With hard wraps
125
+ and other *things*.
126
+ EOE
127
+
128
+ assert rd =~ /<br>/
129
+ end
130
+
131
+ def test_that_link_attributes_work
132
+ rndr = Redcarpet::Render::HTML.new(:link_attributes => {:rel => 'blank'})
133
+ md = Redcarpet::Markdown.new(rndr)
134
+ assert md.render('This is a [simple](http://test.com) test.').include?('rel="blank"')
135
+ end
136
+ end
137
+
138
+ class MarkdownTest < Test::Unit::TestCase
139
+
140
+ def setup
141
+ @markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML)
142
+ end
143
+
144
+ def render_with(flags, text)
145
+ Redcarpet::Markdown.new(Redcarpet::Render::HTML, flags).render(text)
146
+ end
147
+
148
+ def test_that_simple_one_liner_goes_to_html
149
+ assert_respond_to @markdown, :render
150
+ html_equal "<p>Hello World.</p>", @markdown.render("Hello World.")
151
+ end
152
+
153
+ def test_that_inline_markdown_goes_to_html
154
+ markdown = @markdown.render('_Hello World_!')
155
+ html_equal "<p><em>Hello World</em>!</p>", markdown
156
+ end
157
+
158
+ def test_that_inline_markdown_starts_and_ends_correctly
159
+ markdown = render_with({:no_intra_emphasis => true}, '_start _ foo_bar bar_baz _ end_ *italic* **bold** <a>_blah_</a>')
160
+
161
+ html_equal "<p><em>start _ foo_bar bar_baz _ end</em> <em>italic</em> <strong>bold</strong> <a><em>blah</em></a></p>", markdown
162
+
163
+ markdown = @markdown.render("Run 'rake radiant:extensions:rbac_base:migrate'")
164
+ html_equal "<p>Run 'rake radiant:extensions:rbac_base:migrate'</p>", markdown
165
+ end
166
+
167
+ def test_that_urls_are_not_doubly_escaped
168
+ markdown = @markdown.render('[Page 2](/search?query=Markdown+Test&page=2)')
169
+ html_equal "<p><a href=\"/search?query=Markdown+Test&amp;page=2\">Page 2</a></p>\n", markdown
170
+ end
171
+
172
+ def test_simple_inline_html
173
+ #markdown = Markdown.new("before\n\n<div>\n foo\n</div>\nafter")
174
+ markdown = @markdown.render("before\n\n<div>\n foo\n</div>\n\nafter")
175
+ html_equal "<p>before</p>\n\n<div>\n foo\n</div>\n\n<p>after</p>\n", markdown
176
+ end
177
+
178
+ def test_that_html_blocks_do_not_require_their_own_end_tag_line
179
+ markdown = @markdown.render("Para 1\n\n<div><pre>HTML block\n</pre></div>\n\nPara 2 [Link](#anchor)")
180
+ html_equal "<p>Para 1</p>\n\n<div><pre>HTML block\n</pre></div>\n\n<p>Para 2 <a href=\"#anchor\">Link</a></p>\n",
181
+ markdown
182
+ end
183
+
184
+ # This isn't in the spec but is Markdown.pl behavior.
185
+ def test_block_quotes_preceded_by_spaces
186
+ markdown = @markdown.render(
187
+ "A wise man once said:\n\n" +
188
+ " > Isn't it wonderful just to be alive.\n"
189
+ )
190
+ html_equal "<p>A wise man once said:</p>\n\n" +
191
+ "<blockquote><p>Isn't it wonderful just to be alive.</p>\n</blockquote>\n",
192
+ markdown
193
+ end
194
+
195
+ def test_para_before_block_html_should_not_wrap_in_p_tag
196
+ markdown = render_with({:lax_spacing => true},
197
+ "Things to watch out for\n" +
198
+ "<ul>\n<li>Blah</li>\n</ul>\n")
199
+
200
+ html_equal "<p>Things to watch out for</p>\n\n" +
201
+ "<ul>\n<li>Blah</li>\n</ul>\n", markdown
202
+ end
203
+
204
+ # http://github.com/rtomayko/rdiscount/issues/#issue/13
205
+ def test_headings_with_trailing_space
206
+ text = "The Ant-Sugar Tales \n" +
207
+ "=================== \n\n" +
208
+ "By Candice Yellowflower \n"
209
+ html_equal "<h1>The Ant-Sugar Tales </h1>\n\n<p>By Candice Yellowflower </p>\n", @markdown.render(text)
210
+ end
211
+
212
+ def test_that_intra_emphasis_works
213
+ rd = render_with({}, "foo_bar_baz")
214
+ html_equal "<p>foo<em>bar</em>baz</p>\n", rd
215
+
216
+ rd = render_with({:no_intra_emphasis => true},"foo_bar_baz")
217
+ html_equal "<p>foo_bar_baz</p>\n", rd
218
+ end
219
+
220
+ def test_that_autolink_flag_works
221
+ rd = render_with({:autolink => true}, "http://github.com/rtomayko/rdiscount")
222
+ html_equal "<p><a href=\"http://github.com/rtomayko/rdiscount\">http://github.com/rtomayko/rdiscount</a></p>\n", rd
223
+ end
224
+
225
+ if "".respond_to?(:encoding)
226
+ def test_should_return_string_in_same_encoding_as_input
227
+ input = "Yogācāra"
228
+ output = @markdown.render(input)
229
+ assert_equal input.encoding.name, output.encoding.name
230
+ end
231
+
232
+ def test_should_return_string_in_same_encoding_not_in_utf8
233
+ input = "testing".encode('US-ASCII')
234
+ output = @markdown.render(input)
235
+ assert_equal input.encoding.name, output.encoding.name
236
+ end
237
+
238
+ def test_should_accept_non_utf8_or_ascii
239
+ input = "testing \xAB\xCD".force_encoding('ASCII-8BIT')
240
+ output = @markdown.render(input)
241
+ assert_equal 'ASCII-8BIT', output.encoding.name
242
+ end
243
+ end
244
+
245
+ def test_that_tags_can_have_dashes_and_underscores
246
+ rd = @markdown.render("foo <asdf-qwerty>bar</asdf-qwerty> and <a_b>baz</a_b>")
247
+ html_equal "<p>foo <asdf-qwerty>bar</asdf-qwerty> and <a_b>baz</a_b></p>\n", rd
248
+ end
249
+
250
+ def test_link_syntax_is_not_processed_within_code_blocks
251
+ markdown = @markdown.render(" This is a code block\n This is a link [[1]] inside\n")
252
+ html_equal "<pre><code>This is a code block\nThis is a link [[1]] inside\n</code></pre>\n",
253
+ markdown
254
+ end
255
+
256
+ def test_whitespace_after_urls
257
+ rd = render_with({:autolink => true}, "Japan: http://www.abc.net.au/news/events/japan-quake-2011/beforeafter.htm (yes, japan)")
258
+ exp = %{<p>Japan: <a href="http://www.abc.net.au/news/events/japan-quake-2011/beforeafter.htm">http://www.abc.net.au/news/events/japan-quake-2011/beforeafter.htm</a> (yes, japan)</p>}
259
+ html_equal exp, rd
260
+ end
261
+
262
+ def test_memory_leak_when_parsing_char_links
263
+ @markdown.render(<<-leaks)
264
+ 2. Identify the wild-type cluster and determine all clusters
265
+ containing or contained by it:
266
+
267
+ wildtype <- wildtype.cluster(h)
268
+ wildtype.mask <- logical(nclust)
269
+ wildtype.mask[c(contains(h, wildtype),
270
+ wildtype,
271
+ contained.by(h, wildtype))] <- TRUE
272
+
273
+ This could be more elegant.
274
+ leaks
275
+ end
276
+
277
+ def test_infinite_loop_in_header
278
+ html_equal @markdown.render(<<-header), "<h1>Body</h1>"
279
+ ######
280
+ #Body#
281
+ ######
282
+ header
283
+ end
284
+
285
+ def test_that_tables_flag_works
286
+ text = <<EOS
287
+ aaa | bbbb
288
+ -----|------
289
+ hello|sailor
290
+ EOS
291
+
292
+ assert render_with({}, text) !~ /<table/
293
+
294
+ assert render_with({:tables => true}, text) =~ /<table/
295
+ end
296
+
297
+ def test_strikethrough_flag_works
298
+ text = "this is ~some~ striked ~~text~~"
299
+
300
+ assert render_with({}, text) !~ /<del/
301
+
302
+ assert render_with({:strikethrough => true}, text) =~ /<del/
303
+ end
304
+
305
+ def test_that_fenced_flag_works
306
+ text = <<fenced
307
+ This is a simple test
308
+
309
+ ~~~~~
310
+ This is some awesome code
311
+ with tabs and shit
312
+ ~~~
313
+ fenced
314
+
315
+ assert render_with({}, text) !~ /<code/
316
+
317
+ assert render_with({:fenced_code_blocks => true}, text) =~ /<code/
318
+ end
319
+
320
+ def test_that_fenced_flag_works_without_space
321
+ text = "foo\nbar\n```\nsome\ncode\n```\nbaz"
322
+ out = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :fenced_code_blocks => true, :lax_spacing => true).render(text)
323
+ assert out.include?("<pre><code>")
324
+
325
+ out = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :fenced_code_blocks => true).render(text)
326
+ assert !out.include?("<pre><code>")
327
+ end
328
+
329
+ def test_that_headers_are_linkable
330
+ markdown = @markdown.render('### Hello [GitHub](http://github.com)')
331
+ html_equal "<h3>Hello <a href=\"http://github.com\">GitHub</a></h3>", markdown
332
+ end
333
+
334
+ def test_autolinking_with_ent_chars
335
+ markdown = render_with({:autolink => true}, <<text)
336
+ This a stupid link: https://github.com/rtomayko/tilt/issues?milestone=1&state=open
337
+ text
338
+ html_equal "<p>This a stupid link: <a href=\"https://github.com/rtomayko/tilt/issues?milestone=1&state=open\">https://github.com/rtomayko/tilt/issues?milestone=1&amp;state=open</a></p>\n", markdown
339
+ end
340
+
341
+ def test_spaced_headers
342
+ rd = render_with({:space_after_headers => true}, "#123 a header yes\n")
343
+ assert rd !~ /<h1>/
344
+ end
345
+
346
+ def test_proper_intra_emphasis
347
+ md = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :no_intra_emphasis => true)
348
+ assert render_with({:no_intra_emphasis => true}, "http://en.wikipedia.org/wiki/Dave_Allen_(comedian)") !~ /<em>/
349
+ assert render_with({:no_intra_emphasis => true}, "this fails: hello_world_") !~ /<em>/
350
+ assert render_with({:no_intra_emphasis => true}, "this also fails: hello_world_#bye") !~ /<em>/
351
+ assert render_with({:no_intra_emphasis => true}, "this works: hello_my_world") !~ /<em>/
352
+ end
353
+ end
354
+
355
+ class CustomRenderTest < Test::Unit::TestCase
356
+ class SimpleRender < Redcarpet::Render::HTML
357
+ def emphasis(text)
358
+ "<em class=\"cool\">#{text}</em>"
359
+ end
360
+ end
361
+
362
+ def test_simple_overload
363
+ md = Redcarpet::Markdown.new(SimpleRender)
364
+ html_equal "<p>This is <em class=\"cool\">just</em> a test</p>",
365
+ md.render("This is *just* a test")
366
+ end
367
+
368
+ class NilPreprocessRenderer < Redcarpet::Render::HTML
369
+ def preprocess(fulldoc)
370
+ nil
371
+ end
372
+ end
373
+
374
+ def test_preprocess_returning_nil
375
+ md = Redcarpet::Markdown.new(NilPreprocessRenderer)
376
+ assert_equal(nil,md.render("Anything"))
377
+ end
378
+
379
+ end
380
+
381
+ class RedcarpetCompatTest < Test::Unit::TestCase
382
+ def test_simple_compat_api
383
+ html = RedcarpetCompat.new("This is_just_a test").to_html
384
+ html_equal "<p>This is<em>just</em>a test</p>", html
385
+ end
386
+
387
+ def test_compat_api_enables_extensions
388
+ html = RedcarpetCompat.new("This is_just_a test", :no_intra_emphasis).to_html
389
+ html_equal "<p>This is_just_a test</p>", html
390
+ end
391
+
392
+ def test_compat_api_knows_fenced_code_extension
393
+ text = "```ruby\nx = 'foo'\n```"
394
+ html = RedcarpetCompat.new(text, :fenced_code).to_html
395
+ html_equal "<pre><code class=\"ruby\">x = 'foo'\n</code></pre>", html
396
+ end
397
+
398
+ def test_compat_api_ignores_gh_blockcode_extension
399
+ text = "```ruby\nx = 'foo'\n```"
400
+ html = RedcarpetCompat.new(text, :fenced_code, :gh_blockcode).to_html
401
+ html_equal "<pre><code class=\"ruby\">x = 'foo'\n</code></pre>", html
402
+ end
403
+
404
+ def test_compat_api_knows_no_intraemphasis_extension
405
+ html = RedcarpetCompat.new("This is_just_a test", :no_intraemphasis).to_html
406
+ html_equal "<p>This is_just_a test</p>", html
407
+ end
408
+
409
+ def test_translate_outdated_extensions
410
+ # these extensions are no longer used
411
+ exts = [:gh_blockcode, :no_tables, :smart, :strict]
412
+ html = RedcarpetCompat.new('"TEST"', *exts).to_html
413
+ html_equal "<p>&quot;TEST&quot;</p>", html
414
+ end
415
+ end
416
+
417
+ # Disabled by default
418
+ # (these are the easy ones -- the evil ones are not disclosed)
419
+ class PathologicalInputsTest # < Test::Unit::TestCase
420
+ def setup
421
+ @markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML)
422
+ end
423
+
424
+ def test_pathological_1
425
+ star = '*' * 250000
426
+ @markdown.render("#{star}#{star} hi #{star}#{star}")
427
+ end
428
+
429
+ def test_pathological_2
430
+ crt = '^' * 255
431
+ str = "#{crt}(\\)"
432
+ @markdown.render("#{str*300}")
433
+ end
434
+
435
+ def test_pathological_3
436
+ c = "`t`t`t`t`t`t" * 20000000
437
+ @markdown.render(c)
438
+ end
439
+
440
+ def test_pathological_4
441
+ @markdown.render(" [^a]: #{ "A" * 10000 }\n#{ "[^a][]" * 1000000 }\n")
442
+ end
443
+
444
+ def test_unbound_recursion
445
+ @markdown.render(("[" * 10000) + "foo" + ("](bar)" * 10000))
446
+ end
447
+ end