tight-redcarpet 3.1.1 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1547,7 +1547,7 @@ prefix_oli(uint8_t *data, size_t size)
1547
1547
  return i + 2;
1548
1548
  }
1549
1549
 
1550
- /* prefix_uli • returns ordered list item prefix */
1550
+ /* prefix_uli • returns unordered list item prefix */
1551
1551
  static size_t
1552
1552
  prefix_uli(uint8_t *data, size_t size)
1553
1553
  {
@@ -1619,7 +1619,7 @@ parse_blockquote(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
1619
1619
  static size_t
1620
1620
  parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, int do_render);
1621
1621
 
1622
- /* parse_blockquote • handles parsing of a regular paragraph */
1622
+ /* parse_paragraph • handles parsing of a regular paragraph */
1623
1623
  static size_t
1624
1624
  parse_paragraph(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size)
1625
1625
  {
@@ -1630,15 +1630,11 @@ parse_paragraph(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
1630
1630
  while (i < size) {
1631
1631
  for (end = i + 1; end < size && data[end - 1] != '\n'; end++) /* empty */;
1632
1632
 
1633
- if (is_empty(data + i, size - i)) {
1634
- last_is_empty = 1;
1633
+ if (is_empty(data + i, size - i))
1635
1634
  break;
1636
- }
1637
1635
 
1638
- if (!last_is_empty && (level = is_headerline(data + i, size - i)) != 0) {
1639
- last_is_empty = 0;
1636
+ if (!last_is_empty && (level = is_headerline(data + i, size - i)) != 0)
1640
1637
  break;
1641
- }
1642
1638
 
1643
1639
  last_is_empty = 0;
1644
1640
 
@@ -2804,6 +2800,7 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
2804
2800
 
2805
2801
  struct buf *text;
2806
2802
  size_t beg, end;
2803
+ int in_fence = 0;
2807
2804
 
2808
2805
  text = bufnew(64);
2809
2806
  if (!text)
@@ -2815,7 +2812,8 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
2815
2812
  /* reset the references table */
2816
2813
  memset(&md->refs, 0x0, REF_TABLE_SIZE * sizeof(void *));
2817
2814
 
2818
- int footnotes_enabled = md->ext_flags & MKDEXT_FOOTNOTES;
2815
+ int footnotes_enabled = md->ext_flags & MKDEXT_FOOTNOTES;
2816
+ int codefences_enabled = md->ext_flags & MKDEXT_FENCED_CODE;
2819
2817
 
2820
2818
  /* reset the footnotes lists */
2821
2819
  if (footnotes_enabled) {
@@ -2831,10 +2829,13 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
2831
2829
  if (doc_size >= 3 && memcmp(document, UTF8_BOM, 3) == 0)
2832
2830
  beg += 3;
2833
2831
 
2834
- while (beg < doc_size) /* iterating over lines */
2835
- if (footnotes_enabled && is_footnote(document, beg, doc_size, &end, &md->footnotes_found))
2832
+ while (beg < doc_size) { /* iterating over lines */
2833
+ if (codefences_enabled && (is_codefence(document + beg, doc_size - beg, NULL) != 0))
2834
+ in_fence = !in_fence;
2835
+
2836
+ if (!in_fence && footnotes_enabled && is_footnote(document, beg, doc_size, &end, &md->footnotes_found))
2836
2837
  beg = end;
2837
- else if (is_ref(document, beg, doc_size, &end, md->refs))
2838
+ else if (!in_fence && is_ref(document, beg, doc_size, &end, md->refs))
2838
2839
  beg = end;
2839
2840
  else { /* skipping to the next line */
2840
2841
  end = beg;
@@ -2854,6 +2855,7 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
2854
2855
 
2855
2856
  beg = end;
2856
2857
  }
2858
+ }
2857
2859
 
2858
2860
  /* pre-grow the output buffer to minimize allocations */
2859
2861
  bufgrow(ob, MARKDOWN_GROW(text->size));
@@ -104,9 +104,6 @@ struct sd_callbacks {
104
104
  void (*doc_footer)(struct buf *ob, void *opaque);
105
105
  };
106
106
 
107
- /* header methods used internally in Redcarpet */
108
- char* header_anchor(struct buf *text);
109
-
110
107
  struct sd_markdown;
111
108
 
112
109
  /*********
@@ -122,13 +122,9 @@ static VALUE rb_redcarpet_md_render(VALUE self, VALUE text)
122
122
  if (NIL_P(text))
123
123
  return Qnil;
124
124
 
125
- #ifdef HAVE_RUBY_ENCODING_H
126
- {
127
- struct rb_redcarpet_rndr *renderer;
128
- Data_Get_Struct(rb_rndr, struct rb_redcarpet_rndr, renderer);
129
- renderer->options.active_enc = rb_enc_get(text);
130
- }
131
- #endif
125
+ struct rb_redcarpet_rndr *renderer;
126
+ Data_Get_Struct(rb_rndr, struct rb_redcarpet_rndr, renderer);
127
+ renderer->options.active_enc = rb_enc_get(text);
132
128
 
133
129
  /* initialize buffers */
134
130
  output_buf = bufnew(128);
@@ -472,25 +472,30 @@ static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
472
472
  static VALUE rb_redcarpet_htmltoc_init(int argc, VALUE *argv, VALUE self)
473
473
  {
474
474
  struct rb_redcarpet_rndr *rndr;
475
- int nesting_level = 6;
476
- VALUE hash, key = Qnil;
475
+ unsigned int render_flags = HTML_TOC;
476
+ VALUE hash, nesting_level = Qnil;
477
477
 
478
478
  Data_Get_Struct(self, struct rb_redcarpet_rndr, rndr);
479
479
 
480
480
  if (rb_scan_args(argc, argv, "01", &hash) == 1) {
481
481
  Check_Type(hash, T_HASH);
482
482
 
483
- key = CSTR2SYM("nesting_level");
483
+ /* escape_html */
484
+ if (rb_hash_aref(hash, CSTR2SYM("escape_html")) == Qtrue)
485
+ render_flags |= HTML_ESCAPE;
484
486
 
485
- if (RTEST(rb_hash_aref(hash, key))) {
486
- Check_Type(rb_hash_aref(hash, key), T_FIXNUM);
487
- nesting_level = NUM2INT(rb_hash_aref(hash, key));
488
- }
487
+ /* Nesting level */
488
+ nesting_level = rb_hash_aref(hash, CSTR2SYM("nesting_level"));
489
489
  }
490
490
 
491
- sdhtml_toc_renderer(&rndr->callbacks, (struct html_renderopt *)&rndr->options.html, nesting_level);
491
+ sdhtml_toc_renderer(&rndr->callbacks, (struct html_renderopt *)&rndr->options.html, render_flags);
492
492
  rb_redcarpet__overload(self, rb_cRenderHTML_TOC);
493
493
 
494
+ if (!(NIL_P(nesting_level)))
495
+ rndr->options.html.toc_data.nesting_level = NUM2INT(nesting_level);
496
+ else
497
+ rndr->options.html.toc_data.nesting_level = 6;
498
+
494
499
  return Qnil;
495
500
  }
496
501
 
data/lib/redcarpet.rb CHANGED
@@ -1,7 +1,8 @@
1
1
  require 'redcarpet.so'
2
+ require 'redcarpet/compat'
2
3
 
3
4
  module Redcarpet
4
- VERSION = '3.1.1'
5
+ VERSION = '3.2.0'
5
6
 
6
7
  class Markdown
7
8
  attr_reader :renderer
@@ -11,8 +12,8 @@ module Redcarpet
11
12
 
12
13
  # XHTML Renderer
13
14
  class XHTML < HTML
14
- def initialize(extensions={})
15
- super(extensions.merge(:xhtml => true))
15
+ def initialize(extensions = {})
16
+ super(extensions.merge(xhtml: true))
16
17
  end
17
18
  end
18
19
 
@@ -21,6 +22,43 @@ module Redcarpet
21
22
  include SmartyPants
22
23
  end
23
24
 
25
+ # A renderer object you can use to deal with users' input. It
26
+ # enables +escape_html+ and +safe_links_only+ by default.
27
+ #
28
+ # The +block_code+ callback is also overriden not to include
29
+ # the lang's class as the user can basically specify anything
30
+ # with the vanilla one.
31
+ class Safe < HTML
32
+ def initialize(extensions = {})
33
+ super({
34
+ escape_html: true,
35
+ safe_links_only: true
36
+ }.merge(extensions))
37
+ end
38
+
39
+ def block_code(code, lang)
40
+ "<pre>" \
41
+ "<code>#{html_escape(code)}</code>" \
42
+ "</pre>"
43
+ end
44
+
45
+ private
46
+
47
+ # TODO: This is far from ideal to have such method as we
48
+ # are duplicating existing code from Houdini. This method
49
+ # should be defined at the C level.
50
+ def html_escape(string)
51
+ string.gsub(/['&\"<>\/]/, {
52
+ '&' => '&amp;',
53
+ '<' => '&lt;',
54
+ '>' => '&gt;',
55
+ '"' => '&quot;',
56
+ "'" => '&#x27;',
57
+ "/" => '&#x2F',
58
+ })
59
+ end
60
+ end
61
+
24
62
  # SmartyPants Mixin module
25
63
  #
26
64
  # Implements SmartyPants.postprocess, which
@@ -52,74 +90,3 @@ module Redcarpet
52
90
  end
53
91
  end
54
92
  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
- :prettify => :prettify,
81
- :lax_htmlblock => :lax_spacing,
82
- :no_image => :no_images,
83
- :no_intraemphasis => :no_intra_emphasis,
84
- :no_links => :no_links,
85
- :filter_styles => :no_styles,
86
- :safelink => :safe_links_only,
87
- :space_header => :space_after_headers,
88
- :strikethrough => :strikethrough,
89
- :tables => :tables,
90
- :generate_toc => :with_toc_data,
91
- :xhtml => :xhtml,
92
- # old names with no new mapping
93
- :gh_blockcode => nil,
94
- :no_tables => nil,
95
- :smart => nil,
96
- :strict => nil
97
- }
98
-
99
- RENDERER_OPTIONS = [:filter_html, :no_images, :no_links, :no_styles,
100
- :safe_links_only, :with_toc_data, :hard_wrap, :prettify, :xhtml]
101
-
102
- def rename_extensions(exts)
103
- exts.map do |old_name|
104
- if new_name = EXTENSION_MAP[old_name]
105
- new_name
106
- else
107
- old_name
108
- end
109
- end.compact
110
- end
111
-
112
- # Returns two hashes, the extensions and renderer options
113
- # given the extension list
114
- def parse_extensions_and_renderer_options(exts)
115
- exts = rename_extensions(exts)
116
- exts.partition {|ext| !RENDERER_OPTIONS.include?(ext) }.
117
- map {|list| list_to_truthy_hash(list) }
118
- end
119
-
120
- # Turns a list of symbols into a hash of <tt>symbol => true</tt>.
121
- def list_to_truthy_hash(list)
122
- list.inject({}) {|h, k| h[k] = true; h }
123
- end
124
- end
125
-
@@ -1,3 +1,73 @@
1
1
  require 'redcarpet'
2
2
 
3
+ # Creates an instance of Redcarpet with the RedCloth API.
4
+ class RedcarpetCompat
5
+ attr_accessor :text
6
+
7
+ def initialize(text, *exts)
8
+ exts_hash, render_hash = *parse_extensions_and_renderer_options(exts)
9
+ @text = text
10
+ renderer = Redcarpet::Render::HTML.new(render_hash)
11
+ @markdown = Redcarpet::Markdown.new(renderer, exts_hash)
12
+ end
13
+
14
+ def to_html(*_dummy)
15
+ @markdown.render(text)
16
+ end
17
+
18
+ private
19
+
20
+ EXTENSION_MAP = {
21
+ # old name => new name
22
+ :autolink => :autolink,
23
+ :fenced_code => :fenced_code_blocks,
24
+ :filter_html => :filter_html,
25
+ :hard_wrap => :hard_wrap,
26
+ :prettify => :prettify,
27
+ :lax_htmlblock => :lax_spacing,
28
+ :no_image => :no_images,
29
+ :no_intraemphasis => :no_intra_emphasis,
30
+ :no_links => :no_links,
31
+ :filter_styles => :no_styles,
32
+ :safelink => :safe_links_only,
33
+ :space_header => :space_after_headers,
34
+ :strikethrough => :strikethrough,
35
+ :tables => :tables,
36
+ :generate_toc => :with_toc_data,
37
+ :xhtml => :xhtml,
38
+
39
+ # old names with no new mapping
40
+ :gh_blockcode => nil,
41
+ :no_tables => nil,
42
+ :smart => nil,
43
+ :strict => nil
44
+ }
45
+
46
+ RENDERER_OPTIONS = [:filter_html, :no_images, :no_links, :no_styles,
47
+ :safe_links_only, :with_toc_data, :hard_wrap, :prettify, :xhtml]
48
+
49
+ def rename_extensions(exts)
50
+ exts.map do |old_name|
51
+ if new_name = EXTENSION_MAP[old_name]
52
+ new_name
53
+ else
54
+ old_name
55
+ end
56
+ end.compact
57
+ end
58
+
59
+ # Returns two hashes, the extensions and renderer options
60
+ # given the extension list
61
+ def parse_extensions_and_renderer_options(exts)
62
+ exts = rename_extensions(exts)
63
+ exts.partition {|ext| !RENDERER_OPTIONS.include?(ext) }.
64
+ map {|list| list_to_truthy_hash(list) }
65
+ end
66
+
67
+ # Turns a list of symbols into a hash of <tt>symbol => true</tt>.
68
+ def list_to_truthy_hash(list)
69
+ list.inject({}) {|h, k| h[k] = true; h }
70
+ end
71
+ end
72
+
3
73
  Markdown = RedcarpetCompat unless defined? Markdown
@@ -26,9 +26,9 @@ module Redcarpet
26
26
  end
27
27
  end
28
28
 
29
- # Other methods where the text content is in another argument
29
+ # Other methods where we don't return only a specific argument
30
30
  def link(link, title, content)
31
- content
31
+ "#{content} (#{link})"
32
32
  end
33
33
 
34
34
  def image(link, title, content)
data/redcarpet.gemspec CHANGED
@@ -1,10 +1,10 @@
1
1
  # encoding: utf-8
2
2
  Gem::Specification.new do |s|
3
3
  s.name = 'tight-redcarpet'
4
- s.version = '3.1.1'
4
+ s.version = '3.2.0'
5
5
  s.summary = "Markdown that smells nice (patch level 'tight')"
6
6
  s.description = 'A fast, safe and extensible Markdown to (X)HTML parser patched to have smaller headings and no quote-escaping'
7
- s.date = '2014-07-04'
7
+ s.date = '2015-01-08'
8
8
  s.email = 'ujifgc@github.com'
9
9
  s.homepage = 'http://github.com/ujifgc/redcarpet'
10
10
  s.authors = ["Natacha Porté", "Vicent Martí", "Igor Bochkariov"]
@@ -41,16 +41,19 @@ Gem::Specification.new do |s|
41
41
  lib/redcarpet/render_man.rb
42
42
  lib/redcarpet/render_strip.rb
43
43
  redcarpet.gemspec
44
- test/test_helper.rb
44
+ test/benchmark.rb
45
45
  test/custom_render_test.rb
46
+ test/html5_test.rb
46
47
  test/html_render_test.rb
47
48
  test/html_toc_render_test.rb
48
49
  test/markdown_test.rb
49
50
  test/pathological_inputs_test.rb
50
51
  test/redcarpet_compat_test.rb
52
+ test/safe_render_test.rb
51
53
  test/smarty_html_test.rb
52
54
  test/smarty_pants_test.rb
53
55
  test/stripdown_render_test.rb
56
+ test/test_helper.rb
54
57
  ]
55
58
  # = MANIFEST =
56
59
  s.test_files = s.files.grep(%r{^test/})
@@ -59,7 +62,7 @@ Gem::Specification.new do |s|
59
62
  s.executables = ["redcarpet"]
60
63
  s.require_paths = ["lib"]
61
64
 
62
- s.add_development_dependency "nokogiri", "~> 1.6.0"
65
+ s.add_development_dependency "nokogiri", "~> 1.6.3.1"
63
66
  s.add_development_dependency "rake-compiler", "~> 0.8.3"
64
67
  s.add_development_dependency "test-unit", "~> 2.5.4"
65
68
  end
data/test/benchmark.rb ADDED
@@ -0,0 +1,24 @@
1
+ # coding: UTF-8
2
+ # Thanks Kramdown for the inspiration!
3
+ require 'benchmark/ips'
4
+
5
+ require 'redcarpet'
6
+ require 'bluecloth'
7
+ require 'kramdown'
8
+
9
+ markdown = File.read(File.join(File.dirname(__FILE__), "fixtures/benchmark.md"))
10
+
11
+ # Let's bench!
12
+ Benchmark.ips do |bench|
13
+ bench.report("Redcarpet") do
14
+ Redcarpet::Markdown.new(Redcarpet::Render::HTML).render(markdown)
15
+ end
16
+
17
+ bench.report("BlueCloth") do
18
+ BlueCloth.new(markdown).to_html
19
+ end
20
+
21
+ bench.report("Kramdown") do
22
+ Kramdown::Document.new(markdown).to_html
23
+ end
24
+ end
@@ -0,0 +1,69 @@
1
+ require 'test_helper'
2
+
3
+ class HTML5Test < Redcarpet::TestCase
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
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
19
+
20
+ assert_renders section, section
21
+ assert_renders figure, figure
22
+ end
23
+
24
+ def test_that_html5_works_with_code_blocks
25
+ section = <<EOS
26
+ \t<section>
27
+ \t\t<p>The quick brown fox jumps over the lazy dog.</p>
28
+ \t</section>
29
+ EOS
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
37
+
38
+ header = <<EOS
39
+ <header>
40
+ <hgroup>
41
+ <h1>Section heading</h1>
42
+ <h2>Subhead</h2>
43
+ </hgroup>
44
+ </header>
45
+ EOS
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
56
+
57
+ assert_renders section_expected, section
58
+ assert_renders header_expected, header
59
+ end
60
+
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
68
+ end
69
+ end