redcarpet 3.3.4 → 3.5.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.
@@ -92,7 +92,6 @@ typedef size_t
92
92
 
93
93
  static size_t char_emphasis(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
94
94
  static size_t char_underline(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
95
- static size_t char_highlight(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
96
95
  static size_t char_quote(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
97
96
  static size_t char_linebreak(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
98
97
  static size_t char_codespan(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
@@ -613,7 +612,7 @@ parse_emph1(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size
613
612
  if (data[i] == c && !_isspace(data[i - 1])) {
614
613
 
615
614
  if (rndr->ext_flags & MKDEXT_NO_INTRA_EMPHASIS) {
616
- if (i + i < size && _isalnum(data[i + 1]))
615
+ if (i + 1 < size && _isalnum(data[i + 1]))
617
616
  continue;
618
617
  }
619
618
 
@@ -845,7 +844,6 @@ char_quote(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offse
845
844
  return end;
846
845
  }
847
846
 
848
-
849
847
  /* char_escape • '\\' backslash escape */
850
848
  static size_t
851
849
  char_escape(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
@@ -2339,7 +2337,7 @@ parse_table_header(
2339
2337
  if (i < under_end && data[i] != '|' && data[i] != '+')
2340
2338
  break;
2341
2339
 
2342
- if (dashes < 3)
2340
+ if (dashes < 1)
2343
2341
  break;
2344
2342
 
2345
2343
  i++;
@@ -2757,10 +2755,13 @@ sd_markdown_new(
2757
2755
  if (md->cb.emphasis || md->cb.double_emphasis || md->cb.triple_emphasis) {
2758
2756
  md->active_char['*'] = MD_CHAR_EMPHASIS;
2759
2757
  md->active_char['_'] = MD_CHAR_EMPHASIS;
2758
+
2760
2759
  if (extensions & MKDEXT_STRIKETHROUGH)
2761
2760
  md->active_char['~'] = MD_CHAR_EMPHASIS;
2762
2761
  if (extensions & MKDEXT_HIGHLIGHT)
2763
2762
  md->active_char['='] = MD_CHAR_EMPHASIS;
2763
+ if (extensions & MKDEXT_QUOTE)
2764
+ md->active_char['"'] = MD_CHAR_QUOTE;
2764
2765
  }
2765
2766
 
2766
2767
  if (md->cb.codespan)
@@ -2785,9 +2786,6 @@ sd_markdown_new(
2785
2786
  if (extensions & MKDEXT_SUPERSCRIPT)
2786
2787
  md->active_char['^'] = MD_CHAR_SUPERSCRIPT;
2787
2788
 
2788
- if (extensions & MKDEXT_QUOTE)
2789
- md->active_char['"'] = MD_CHAR_QUOTE;
2790
-
2791
2789
  /* Extension data */
2792
2790
  md->ext_flags = extensions;
2793
2791
  md->opaque = opaque;
@@ -24,6 +24,7 @@
24
24
 
25
25
  VALUE rb_mRedcarpet;
26
26
  VALUE rb_cMarkdown;
27
+ VALUE rb_cRenderHTML_TOC;
27
28
 
28
29
  extern VALUE rb_cRenderBase;
29
30
 
@@ -86,7 +87,7 @@ rb_redcarpet_md__free(void *markdown)
86
87
 
87
88
  static VALUE rb_redcarpet_md__new(int argc, VALUE *argv, VALUE klass)
88
89
  {
89
- VALUE rb_markdown, rb_rndr, hash;
90
+ VALUE rb_markdown, rb_rndr, hash, rndr_options;
90
91
  unsigned int extensions = 0;
91
92
 
92
93
  struct rb_redcarpet_rndr *rndr;
@@ -101,8 +102,23 @@ static VALUE rb_redcarpet_md__new(int argc, VALUE *argv, VALUE klass)
101
102
  if (!rb_obj_is_kind_of(rb_rndr, rb_cRenderBase))
102
103
  rb_raise(rb_eTypeError, "Invalid Renderer instance given");
103
104
 
105
+ /**
106
+ * Automatically enable the `fenced_code_blocks` option if
107
+ * given a kind of `HTML_TOC` object since many languages
108
+ * like Ruby use the sharp to comment code so these comments
109
+ * would be processed as titles.
110
+ */
111
+ if (rb_obj_is_kind_of(rb_rndr, rb_cRenderHTML_TOC))
112
+ extensions |= MKDEXT_FENCED_CODE;
113
+
104
114
  Data_Get_Struct(rb_rndr, struct rb_redcarpet_rndr, rndr);
105
115
 
116
+ /* Merge the current options in the @options hash */
117
+ if (hash != Qnil) {
118
+ rndr_options = rb_funcall(rb_iv_get(rb_rndr, "@options"), rb_intern("merge"), 1, hash);
119
+ rb_iv_set(rb_rndr, "@options", rndr_options);
120
+ }
121
+
106
122
  markdown = sd_markdown_new(extensions, 16, &rndr->callbacks, &rndr->options);
107
123
  if (!markdown)
108
124
  rb_raise(rb_eRuntimeError, "Failed to create new Renderer class");
@@ -165,4 +181,3 @@ void Init_redcarpet()
165
181
 
166
182
  Init_redcarpet_rndr();
167
183
  }
168
-
@@ -40,10 +40,10 @@
40
40
  }
41
41
 
42
42
  extern VALUE rb_mRedcarpet;
43
+ extern VALUE rb_cRenderHTML_TOC;
43
44
  VALUE rb_mRender;
44
45
  VALUE rb_cRenderBase;
45
46
  VALUE rb_cRenderHTML;
46
- VALUE rb_cRenderHTML_TOC;
47
47
  VALUE rb_mSmartyPants;
48
48
 
49
49
  #define buf2str(t) ((t) ? rb_enc_str_new((const char*)(t)->data, (t)->size, opt->active_enc) : Qnil)
@@ -390,6 +390,7 @@ static VALUE rb_redcarpet_rbase_alloc(VALUE klass)
390
390
  static void rb_redcarpet__overload(VALUE self, VALUE base_class)
391
391
  {
392
392
  struct rb_redcarpet_rndr *rndr;
393
+ VALUE options_ivar;
393
394
 
394
395
  Data_Get_Struct(self, struct rb_redcarpet_rndr, rndr);
395
396
  rndr->options.self = self;
@@ -410,6 +411,10 @@ static void rb_redcarpet__overload(VALUE self, VALUE base_class)
410
411
  dest[i] = source[i];
411
412
  }
412
413
  }
414
+
415
+ options_ivar = rb_attr_get(self, rb_intern("@options"));
416
+ if (options_ivar == Qundef || options_ivar == Qnil)
417
+ rb_iv_set(self, "@options", rb_hash_new());
413
418
  }
414
419
 
415
420
  static VALUE rb_redcarpet_rbase_init(VALUE self)
@@ -429,6 +434,9 @@ static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
429
434
  if (rb_scan_args(argc, argv, "01", &hash) == 1) {
430
435
  Check_Type(hash, T_HASH);
431
436
 
437
+ /* Give access to the passed options through `@options` */
438
+ rb_iv_set(self, "@options", hash);
439
+
432
440
  /* escape_html */
433
441
  if (rb_hash_aref(hash, CSTR2SYM("escape_html")) == Qtrue)
434
442
  render_flags |= HTML_ESCAPE;
@@ -491,6 +499,9 @@ static VALUE rb_redcarpet_htmltoc_init(int argc, VALUE *argv, VALUE self)
491
499
  if (rb_scan_args(argc, argv, "01", &hash) == 1) {
492
500
  Check_Type(hash, T_HASH);
493
501
 
502
+ /* Give access to the passed options through `@options` */
503
+ rb_iv_set(self, "@options", hash);
504
+
494
505
  /* escape_html */
495
506
  if (rb_hash_aref(hash, CSTR2SYM("escape_html")) == Qtrue)
496
507
  render_flags |= HTML_ESCAPE;
@@ -502,10 +513,22 @@ static VALUE rb_redcarpet_htmltoc_init(int argc, VALUE *argv, VALUE self)
502
513
  sdhtml_toc_renderer(&rndr->callbacks, (struct html_renderopt *)&rndr->options.html, render_flags);
503
514
  rb_redcarpet__overload(self, rb_cRenderHTML_TOC);
504
515
 
505
- if (!(NIL_P(nesting_level)))
506
- rndr->options.html.toc_data.nesting_level = NUM2INT(nesting_level);
507
- else
508
- rndr->options.html.toc_data.nesting_level = 6;
516
+ /* Check whether we are dealing with a Range object by
517
+ checking whether the object responds to min and max */
518
+ if (rb_respond_to(nesting_level, rb_intern("min")) &&
519
+ rb_respond_to(nesting_level, rb_intern("max"))) {
520
+ int min = NUM2INT(rb_funcall(nesting_level, rb_intern("min"), 0));
521
+ int max = NUM2INT(rb_funcall(nesting_level, rb_intern("max"), 0));
522
+
523
+ rndr->options.html.toc_data.nesting_bounds[0] = min;
524
+ rndr->options.html.toc_data.nesting_bounds[1] = max;
525
+ } else if (FIXNUM_P(nesting_level)) {
526
+ rndr->options.html.toc_data.nesting_bounds[0] = 1;
527
+ rndr->options.html.toc_data.nesting_bounds[1] = NUM2INT(nesting_level);
528
+ } else {
529
+ rndr->options.html.toc_data.nesting_bounds[0] = 1;
530
+ rndr->options.html.toc_data.nesting_bounds[1] = 6;
531
+ }
509
532
 
510
533
  return Qnil;
511
534
  }
data/lib/redcarpet/cli.rb CHANGED
@@ -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,5 +1,3 @@
1
- require 'redcarpet'
2
-
3
1
  # Creates an instance of Redcarpet with the RedCloth API.
4
2
  class RedcarpetCompat
5
3
  attr_accessor :text
@@ -13,7 +13,7 @@ module Redcarpet
13
13
  :autolink, :codespan, :double_emphasis,
14
14
  :emphasis, :underline, :raw_html,
15
15
  :triple_emphasis, :strikethrough,
16
- :superscript, :highlight,
16
+ :superscript, :highlight, :quote,
17
17
 
18
18
  # footnotes
19
19
  :footnotes, :footnote_def, :footnote_ref,
data/lib/redcarpet.rb CHANGED
@@ -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.5.1'
6
6
 
7
7
  class Markdown
8
8
  attr_reader :renderer
data/redcarpet.gemspec CHANGED
@@ -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.5.1'
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 = '2020-12-15'
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-compiler", "~> 0.9.5"
69
- s.add_development_dependency "test-unit", "~> 3.1.3"
68
+ s.add_development_dependency "rake", "~> 12.2.1"
69
+ s.add_development_dependency "rake-compiler", "~> 1.0.3"
70
+ s.add_development_dependency "test-unit", "~> 3.2.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,30 @@ 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
+
39
+ def test_original_options_hash_is_not_mutated
40
+ options = { with_toc_data: true }
41
+ render = SimpleRender.new(options)
42
+ parser = Redcarpet::Markdown.new(render, tables: true)
43
+
44
+ computed_options = render.instance_variable_get(:"@options")
45
+
46
+ refute_equal computed_options.object_id, options.object_id
47
+ end
48
+
17
49
  class NilPreprocessRenderer < Redcarpet::Render::HTML
18
50
  def preprocess(fulldoc)
19
51
  nil
@@ -25,4 +57,11 @@ class CustomRenderTest < Redcarpet::TestCase
25
57
  assert_equal(nil,md.render("Anything"))
26
58
  end
27
59
 
60
+ def test_base_render_without_quote_callback
61
+ # Regression test for https://github.com/vmg/redcarpet/issues/569
62
+ render = Class.new(Redcarpet::Render::Base)
63
+ parser = Redcarpet::Markdown.new render.new, quote: true
64
+
65
+ assert_equal "", parser.render(%(a "quote"))
66
+ end
28
67
  end
data/test/html5_test.rb CHANGED
@@ -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">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">&#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,28 @@ 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
+ if 1.size == 4 # 32-bit architecture
258
+ html = "<h1 id=\"part-a194139f\">見出し</h1>"
259
+ elsif 1.size == 8 # 64-bit architecture
260
+ html = "<h1 id=\"part-37870bfa194139f\">見出し</h1>"
261
+ else
262
+ raise "unknown integer size"
263
+ end
264
+
265
+ assert_equal html, render(markdown, with: [:with_toc_data])
266
+ end
267
+
268
+ def test_escape_entities_removal_from_anchor
269
+ output = render("# Foo's & Bar's", with: [:with_toc_data])
270
+ result = %(<h1 id="foos-bars">Foo&#39;s &amp; Bar&#39;s</h1>)
271
+
272
+ assert_equal result, output
273
+ end
248
274
  end