redcarpet 3.3.4 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of redcarpet might be problematic. Click here for more details.

@@ -86,7 +86,7 @@ rb_redcarpet_md__free(void *markdown)
86
86
 
87
87
  static VALUE rb_redcarpet_md__new(int argc, VALUE *argv, VALUE klass)
88
88
  {
89
- VALUE rb_markdown, rb_rndr, hash;
89
+ VALUE rb_markdown, rb_rndr, hash, rndr_options;
90
90
  unsigned int extensions = 0;
91
91
 
92
92
  struct rb_redcarpet_rndr *rndr;
@@ -103,6 +103,12 @@ static VALUE rb_redcarpet_md__new(int argc, VALUE *argv, VALUE klass)
103
103
 
104
104
  Data_Get_Struct(rb_rndr, struct rb_redcarpet_rndr, rndr);
105
105
 
106
+ /* Merge the current options in the @options hash */
107
+ if (hash != Qnil) {
108
+ rndr_options = rb_iv_get(rb_rndr, "@options");
109
+ rb_funcall(rndr_options, rb_intern("merge!"), 1, hash);
110
+ }
111
+
106
112
  markdown = sd_markdown_new(extensions, 16, &rndr->callbacks, &rndr->options);
107
113
  if (!markdown)
108
114
  rb_raise(rb_eRuntimeError, "Failed to create new Renderer class");
@@ -410,6 +410,9 @@ static void rb_redcarpet__overload(VALUE self, VALUE base_class)
410
410
  dest[i] = source[i];
411
411
  }
412
412
  }
413
+
414
+ if (rb_iv_get(self, "@options") == Qnil)
415
+ rb_iv_set(self, "@options", rb_hash_new());
413
416
  }
414
417
 
415
418
  static VALUE rb_redcarpet_rbase_init(VALUE self)
@@ -429,6 +432,9 @@ static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
429
432
  if (rb_scan_args(argc, argv, "01", &hash) == 1) {
430
433
  Check_Type(hash, T_HASH);
431
434
 
435
+ /* Give access to the passed options through `@options` */
436
+ rb_iv_set(self, "@options", hash);
437
+
432
438
  /* escape_html */
433
439
  if (rb_hash_aref(hash, CSTR2SYM("escape_html")) == Qtrue)
434
440
  render_flags |= HTML_ESCAPE;
@@ -491,6 +497,9 @@ static VALUE rb_redcarpet_htmltoc_init(int argc, VALUE *argv, VALUE self)
491
497
  if (rb_scan_args(argc, argv, "01", &hash) == 1) {
492
498
  Check_Type(hash, T_HASH);
493
499
 
500
+ /* Give access to the passed options through `@options` */
501
+ rb_iv_set(self, "@options", hash);
502
+
494
503
  /* escape_html */
495
504
  if (rb_hash_aref(hash, CSTR2SYM("escape_html")) == Qtrue)
496
505
  render_flags |= HTML_ESCAPE;
@@ -2,7 +2,7 @@ require 'redcarpet.so'
2
2
  require 'redcarpet/compat'
3
3
 
4
4
  module Redcarpet
5
- VERSION = '3.3.4'
5
+ VERSION = '3.4.0'
6
6
 
7
7
  class Markdown
8
8
  attr_reader :renderer
@@ -47,7 +47,7 @@ module Redcarpet
47
47
  end
48
48
 
49
49
  opts.on_tail("-v", "--version", "Display the current version") do
50
- STDOUT.write "Redcarpet #{Redcarpet::VERSION}"
50
+ STDOUT.puts "Redcarpet #{Redcarpet::VERSION}"
51
51
  exit
52
52
  end
53
53
 
@@ -1,10 +1,10 @@
1
1
  # encoding: utf-8
2
2
  Gem::Specification.new do |s|
3
3
  s.name = 'redcarpet'
4
- s.version = '3.3.4'
4
+ s.version = '3.4.0'
5
5
  s.summary = "Markdown that smells nice"
6
6
  s.description = 'A fast, safe and extensible Markdown to (X)HTML parser'
7
- s.date = '2015-12-25'
7
+ s.date = '2016-12-25'
8
8
  s.email = 'vicent@github.com'
9
9
  s.homepage = 'http://github.com/vmg/redcarpet'
10
10
  s.authors = ["Natacha Porté", "Vicent Martí"]
@@ -65,6 +65,7 @@ Gem::Specification.new do |s|
65
65
  s.executables = ["redcarpet"]
66
66
  s.require_paths = ["lib"]
67
67
 
68
+ s.add_development_dependency "rake", "~> 10.5"
68
69
  s.add_development_dependency "rake-compiler", "~> 0.9.5"
69
70
  s.add_development_dependency "test-unit", "~> 3.1.3"
70
71
  end
@@ -4,7 +4,15 @@ require 'test_helper'
4
4
  class CustomRenderTest < Redcarpet::TestCase
5
5
  class SimpleRender < Redcarpet::Render::HTML
6
6
  def emphasis(text)
7
- "<em class=\"cool\">#{text}</em>"
7
+ if @options[:no_intra_emphasis]
8
+ return %(<em class="no_intra_emphasis">#{text}</em>)
9
+ end
10
+
11
+ %(<em class="cool">#{text}</em>)
12
+ end
13
+
14
+ def header(text, level)
15
+ "My little poney" if @options[:with_toc_data]
8
16
  end
9
17
  end
10
18
 
@@ -14,6 +22,20 @@ class CustomRenderTest < Redcarpet::TestCase
14
22
  md.render("This is *just* a test")
15
23
  end
16
24
 
25
+ def test_renderer_options
26
+ parser = Redcarpet::Markdown.new(SimpleRender.new(with_toc_data: true))
27
+ output = parser.render("# A title")
28
+
29
+ assert_match "My little poney", output
30
+ end
31
+
32
+ def test_markdown_options
33
+ parser = Redcarpet::Markdown.new(SimpleRender, no_intra_emphasis: true)
34
+ output = parser.render("*foo*")
35
+
36
+ assert_match "no_intra_emphasis", output
37
+ end
38
+
17
39
  class NilPreprocessRenderer < Redcarpet::Render::HTML
18
40
  def preprocess(fulldoc)
19
41
  nil
@@ -25,4 +47,11 @@ class CustomRenderTest < Redcarpet::TestCase
25
47
  assert_equal(nil,md.render("Anything"))
26
48
  end
27
49
 
50
+ def test_base_render_without_quote_callback
51
+ # Regression test for https://github.com/vmg/redcarpet/issues/569
52
+ render = Class.new(Redcarpet::Render::Base)
53
+ parser = Redcarpet::Markdown.new render.new, quote: true
54
+
55
+ assert_equal "", parser.render(%(a "quote"))
56
+ end
28
57
  end
@@ -2,68 +2,81 @@ require 'test_helper'
2
2
 
3
3
  class HTML5Test < Redcarpet::TestCase
4
4
  def test_that_html5_works
5
- section = <<EOS
6
- <section>
7
- <p>The quick brown fox jumps over the lazy dog.</p>
8
- </section>
9
- EOS
5
+ section = <<-HTML.chomp.strip_heredoc
6
+ <section>
7
+ <p>The quick brown fox jumps over the lazy dog.</p>
8
+ </section>
9
+ HTML
10
10
 
11
- figure = <<EOS
12
- <figure>
13
- <img src="http://example.org/image.jpg" alt="">
14
- <figcaption>
15
- <p>Hello world!</p>
16
- </figcaption>
17
- </figure>
18
- EOS
11
+ figure = <<-HTML.chomp.strip_heredoc
12
+ <figure>
13
+ <img src="http://example.org/image.jpg" alt="">
14
+ <figcaption>
15
+ <p>Hello world!</p>
16
+ </figcaption>
17
+ </figure>
18
+ HTML
19
19
 
20
20
  assert_renders section, section
21
21
  assert_renders figure, figure
22
22
  end
23
23
 
24
24
  def test_that_html5_works_with_code_blocks
25
- section = <<EOS
25
+ section = <<-HTML
26
26
  \t<section>
27
27
  \t\t<p>The quick brown fox jumps over the lazy dog.</p>
28
28
  \t</section>
29
- EOS
29
+ HTML
30
30
 
31
- section_expected = <<EOE
32
- <pre><code>&lt;section&gt;
33
- &lt;p&gt;The quick brown fox jumps over the lazy dog.&lt;/p&gt;
34
- &lt;/section&gt;
35
- </code></pre>
36
- EOE
31
+ section_expected = <<-HTML.chomp.strip_heredoc
32
+ <pre><code>&lt;section&gt;
33
+ &lt;p&gt;The quick brown fox jumps over the lazy dog.&lt;/p&gt;
34
+ &lt;/section&gt;
35
+ </code></pre>
36
+ HTML
37
37
 
38
- header = <<EOS
38
+ header = <<-HTML
39
39
  <header>
40
40
  <hgroup>
41
41
  <h1>Section heading</h1>
42
42
  <h2>Subhead</h2>
43
43
  </hgroup>
44
44
  </header>
45
- EOS
45
+ HTML
46
46
 
47
- header_expected = <<EOE
48
- <pre><code>&lt;header&gt;
49
- &lt;hgroup&gt;
50
- &lt;h1&gt;Section heading&lt;/h1&gt;
51
- &lt;h2&gt;Subhead&lt;/h2&gt;
52
- &lt;/hgroup&gt;
53
- &lt;/header&gt;
54
- </code></pre>
55
- EOE
47
+ header_expected = <<-HTML.chomp.strip_heredoc
48
+ <pre><code>&lt;header&gt;
49
+ &lt;hgroup&gt;
50
+ &lt;h1&gt;Section heading&lt;/h1&gt;
51
+ &lt;h2&gt;Subhead&lt;/h2&gt;
52
+ &lt;/hgroup&gt;
53
+ &lt;/header&gt;
54
+ </code></pre>
55
+ HTML
56
56
 
57
57
  assert_renders section_expected, section
58
58
  assert_renders header_expected, header
59
59
  end
60
60
 
61
61
  def test_script_tag_recognition
62
- markdown = <<-Md
63
- <script type="text/javascript">
64
- alert('Foo!');
65
- </script>
66
- Md
67
- assert_renders markdown, markdown
62
+ html = <<-HTML.chomp.strip_heredoc
63
+ <script type="text/javascript">
64
+ alert('Foo!');
65
+ </script>
66
+ HTML
67
+
68
+ assert_renders html, html
69
+ end
70
+
71
+ def test_new_html5_tags_not_escaped
72
+ details = <<-HTML.chomp.strip_heredoc
73
+ <details>
74
+ log:
75
+
76
+ </details>
77
+ HTML
78
+
79
+ assert_renders details, details
68
80
  end
81
+
69
82
  end
@@ -8,20 +8,20 @@ class HTMLRenderTest < Redcarpet::TestCase
8
8
 
9
9
  # Hint: overrides filter_html, no_images and no_links
10
10
  def test_that_escape_html_works
11
- source = <<EOS
12
- Through <em>NO</em> <script>DOUBLE NO</script>
11
+ source = <<-HTML.strip_heredoc
12
+ Through <em>NO</em> <script>DOUBLE NO</script>
13
13
 
14
- <script>BAD</script>
14
+ <script>BAD</script>
15
15
 
16
- <img src="/favicon.ico" />
17
- EOS
18
- expected = <<EOE
19
- <p>Through &lt;em&gt;NO&lt;/em&gt; &lt;script&gt;DOUBLE NO&lt;/script&gt;</p>
16
+ <img src="/favicon.ico" />
17
+ HTML
18
+ expected = <<-HTML.chomp.strip_heredoc
19
+ <p>Through &lt;em&gt;NO&lt;/em&gt; &lt;script&gt;DOUBLE NO&lt;/script&gt;</p>
20
20
 
21
- <p>&lt;script&gt;BAD&lt;/script&gt;</p>
21
+ <p>&lt;script&gt;BAD&lt;/script&gt;</p>
22
22
 
23
- <p>&lt;img src=&quot;/favicon.ico&quot; /&gt;</p>
24
- EOE
23
+ <p>&lt;img src=&quot;/favicon.ico&quot; /&gt;</p>
24
+ HTML
25
25
 
26
26
  assert_equal expected, render(source, with: [:escape_html])
27
27
  end
@@ -30,14 +30,14 @@ EOE
30
30
  markdown = 'Through <em>NO</em> <script>DOUBLE NO</script>'
31
31
  output = render(markdown, with: [:filter_html])
32
32
 
33
- assert_equal "<p>Through NO DOUBLE NO</p>\n", output
33
+ assert_equal "<p>Through NO DOUBLE NO</p>", output
34
34
  end
35
35
 
36
36
  def test_filter_html_doesnt_break_two_space_hard_break
37
37
  markdown = "Lorem, \nipsum\n"
38
38
  output = render(markdown, with: [:filter_html])
39
39
 
40
- assert_equal "<p>Lorem,<br>\nipsum</p>\n", output
40
+ assert_equal "<p>Lorem,<br>\nipsum</p>", output
41
41
  end
42
42
 
43
43
  def test_that_no_image_flag_works
@@ -47,6 +47,12 @@ EOE
47
47
  assert_no_match %r{<img}, output
48
48
  end
49
49
 
50
+ def test_that_links_with_ampersands_work
51
+ markdown = %([/?a=b&c=d](/?a=b&c=d))
52
+ output = render(markdown)
53
+ assert_equal "<p><a href=\"/?a=b&c=d\">/?a=b&amp;c=d</a></p>", output
54
+ end
55
+
50
56
  def test_that_no_links_flag_works
51
57
  markdown = %([This link](http://example.net/) <a href="links.html">links</a>)
52
58
  output = render(markdown, with: [:no_links])
@@ -58,17 +64,17 @@ EOE
58
64
  markdown = "[IRC](irc://chat.freenode.org/#freenode)"
59
65
  output = render(markdown, with: [:safe_links_only])
60
66
 
61
- assert_equal "<p>[IRC](irc://chat.freenode.org/#freenode)</p>\n", output
67
+ assert_equal "<p>[IRC](irc://chat.freenode.org/#freenode)</p>", output
62
68
  end
63
69
 
64
70
  def test_that_hard_wrap_works
65
- markdown = <<EOE
66
- Hello world,
67
- this is just a simple test
71
+ markdown = <<-Markdown.strip_heredoc
72
+ Hello world,
73
+ this is just a simple test
68
74
 
69
- With hard wraps
70
- and other *things*.
71
- EOE
75
+ With hard wraps
76
+ and other *things*.
77
+ Markdown
72
78
  output = render(markdown, with: [:hard_wrap])
73
79
 
74
80
  assert_match %r{<br>}, output
@@ -82,37 +88,37 @@ EOE
82
88
 
83
89
  def test_that_link_works_with_quotes
84
90
  markdown = %([This'link"is](http://example.net/))
85
- expected = %(<p><a href="http://example.net/">This&#39;link&quot;is</a></p>\n)
91
+ expected = %(<p><a href="http://example.net/">This&#39;link&quot;is</a></p>)
86
92
 
87
93
  assert_equal expected, render(markdown)
88
94
  assert_equal expected, render(markdown, with: [:escape_html])
89
95
  end
90
96
 
91
97
  def test_that_code_emphasis_work
92
- markdown = <<-MD
93
- This should be **`a bold codespan`**
94
- However, this should be *`an emphasised codespan`*
98
+ markdown = <<-Markdown.strip_heredoc
99
+ This should be **`a bold codespan`**
100
+ However, this should be *`an emphasised codespan`*
95
101
 
96
- * **`ABC`** or **`DEF`**
97
- * Foo bar
98
- MD
102
+ * **`ABC`** or **`DEF`**
103
+ * Foo bar
104
+ Markdown
99
105
 
100
- html = <<HTML
101
- <p>This should be <strong><code>a bold codespan</code></strong>
102
- However, this should be <em><code>an emphasised codespan</code></em></p>
106
+ html = <<-HTML.chomp.strip_heredoc
107
+ <p>This should be <strong><code>a bold codespan</code></strong>
108
+ However, this should be <em><code>an emphasised codespan</code></em></p>
103
109
 
104
- <ul>
105
- <li><strong><code>ABC</code></strong> or <strong><code>DEF</code></strong></li>
106
- <li>Foo bar</li>
107
- </ul>
108
- HTML
110
+ <ul>
111
+ <li><strong><code>ABC</code></strong> or <strong><code>DEF</code></strong></li>
112
+ <li>Foo bar</li>
113
+ </ul>
114
+ HTML
109
115
 
110
116
  assert_equal html, render(markdown)
111
117
  end
112
118
 
113
119
  def test_that_parenthesis_are_handled_into_links
114
120
  markdown = %(The [bash man page](man:bash(1))!)
115
- expected = %(<p>The <a href="man:bash(1)">bash man page</a>!</p>\n)
121
+ expected = %(<p>The <a href="man:bash(1)">bash man page</a>!</p>)
116
122
 
117
123
  assert_equal expected, render(markdown)
118
124
  end
@@ -127,42 +133,42 @@ HTML
127
133
  end
128
134
 
129
135
  def test_that_footnotes_work
130
- markdown = <<-MD
131
- This is a footnote.[^1]
136
+ markdown = <<-Markdown.strip_heredoc
137
+ This is a footnote.[^1]
132
138
 
133
- [^1]: It provides additional information.
134
- MD
139
+ [^1]: It provides additional information.
140
+ Markdown
135
141
 
136
- html = <<HTML
137
- <p>This is a footnote.<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup></p>
142
+ html = <<-HTML.chomp.strip_heredoc
143
+ <p>This is a footnote.<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup></p>
138
144
 
139
- <div class="footnotes">
140
- <hr>
141
- <ol>
145
+ <div class="footnotes">
146
+ <hr>
147
+ <ol>
142
148
 
143
- <li id="fn1">
144
- <p>It provides additional information.&nbsp;<a href="#fnref1" rev="footnote">&#8617;</a></p>
145
- </li>
149
+ <li id="fn1">
150
+ <p>It provides additional information.&nbsp;<a href="#fnref1" rev="footnote">&#8617;</a></p>
151
+ </li>
146
152
 
147
- </ol>
148
- </div>
149
- HTML
153
+ </ol>
154
+ </div>
155
+ HTML
150
156
 
151
157
  output = render(markdown, with: [:footnotes])
152
158
  assert_equal html, output
153
159
  end
154
160
 
155
161
  def test_footnotes_enabled_but_missing_marker
156
- markdown = <<MD
157
- Some text without a marker
162
+ markdown = <<-Markdown.strip_heredoc
163
+ Some text without a marker
158
164
 
159
- [^1] And a trailing definition
160
- MD
161
- html = <<HTML
162
- <p>Some text without a marker</p>
165
+ [^1] And a trailing definition
166
+ Markdown
167
+ html = <<-HTML.chomp.strip_heredoc
168
+ <p>Some text without a marker</p>
163
169
 
164
- <p>[^1] And a trailing definition</p>
165
- HTML
170
+ <p>[^1] And a trailing definition</p>
171
+ HTML
166
172
 
167
173
  output = render(markdown, with: [:footnotes])
168
174
  assert_equal html, output
@@ -170,7 +176,7 @@ HTML
170
176
 
171
177
  def test_footnotes_enabled_but_missing_definition
172
178
  markdown = "Some text with a marker[^1] but no definition."
173
- expected = "<p>Some text with a marker[^1] but no definition.</p>\n"
179
+ expected = "<p>Some text with a marker[^1] but no definition.</p>"
174
180
 
175
181
  output = render(markdown, with: [:footnotes])
176
182
  assert_equal expected, output
@@ -241,8 +247,22 @@ HTML
241
247
 
242
248
  def test_non_ascii_removal_in_header_anchors
243
249
  markdown = "# Glühlampe"
244
- html = "<h1 id=\"gl-hlampe\">Glühlampe</h1>\n"
250
+ html = "<h1 id=\"gl-hlampe\">Glühlampe</h1>"
245
251
 
246
252
  assert_equal html, render(markdown, with: [:with_toc_data])
247
253
  end
254
+
255
+ def test_utf8_only_header_anchors
256
+ markdown = "# 見出し"
257
+ html = "<h1 id=\"part-37870bfa194139f\">見出し</h1>"
258
+
259
+ assert_equal html, render(markdown, with: [:with_toc_data])
260
+ end
261
+
262
+ def test_escape_entities_removal_from_anchor
263
+ output = render("# Foo's & Bar's", with: [:with_toc_data])
264
+ result = %(<h1 id="foos-bars">Foo&#39;s &amp; Bar&#39;s</h1>)
265
+
266
+ assert_equal result, output
267
+ end
248
268
  end