vkhater-redcarpet 2.2.3

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,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