From 27dfb2a738a23aadd286ac9e7ecd61c4545d29de Mon Sep 17 00:00:00 2001 From: Mark Lambley Date: Sun, 28 Feb 2021 19:30:16 +0100 Subject: [PATCH] Provide the header bit in the `table_cell` callback As the same callback is used to render header and body cells, there is an extra bit needed to check in which one we are currently rendering the content. Fixes #604. --- CHANGELOG.md | 9 +++++++++ README.markdown | 2 +- ext/redcarpet/rc_render.c | 25 +++++++++++++++++++++--- test/custom_render_test.rb | 39 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f551d0cd..19385029 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +* Properly provide a third argument to the `table_cell` callback indicating + whether the current cell is part of the header or not. + + The previous implementation with two parameters is still supported. + + Fixes #604, Refs #605. + + *Mark Lambley* + * Fix anchor generation on titles with ampersands. Fixes #696. diff --git a/README.markdown b/README.markdown index 7775d57e..b9764ba0 100644 --- a/README.markdown +++ b/README.markdown @@ -258,7 +258,7 @@ end * paragraph(text) * table(header, body) * table_row(content) -* table_cell(content, alignment) +* table_cell(content, alignment, header) ### Span-level calls diff --git a/ext/redcarpet/rc_render.c b/ext/redcarpet/rc_render.c index 26568ac7..e527c1c8 100644 --- a/ext/redcarpet/rc_render.c +++ b/ext/redcarpet/rc_render.c @@ -113,9 +113,10 @@ rndr_tablerow(struct buf *ob, const struct buf *text, void *opaque) static void rndr_tablecell(struct buf *ob, const struct buf *text, int align, void *opaque) { - VALUE rb_align; + VALUE rb_align, rb_header; + VALUE rb_callback, rb_callback_arity; - switch (align) { + switch (align & MKD_TABLE_ALIGNMASK) { case MKD_TABLE_ALIGN_L: rb_align = CSTR2SYM("left"); break; @@ -133,7 +134,25 @@ rndr_tablecell(struct buf *ob, const struct buf *text, int align, void *opaque) break; } - BLOCK_CALLBACK("table_cell", 2, buf2str(text), rb_align); + if (align & MKD_TABLE_HEADER) { + rb_header = Qtrue; + } else { + rb_header = Qfalse; + } + + struct redcarpet_renderopt *opt = opaque; + + rb_callback = rb_funcall(opt->self, rb_intern("method"), 1, CSTR2SYM("table_cell")); + + rb_callback_arity = rb_funcall(rb_callback, rb_intern("arity"), 0); + + /* For backward compatibility, let's ensure that the erasure with + only two parameters is still supported. */ + if (FIX2SHORT(rb_callback_arity) == 3) { + BLOCK_CALLBACK("table_cell", 3, buf2str(text), rb_align, rb_header); + } else { + BLOCK_CALLBACK("table_cell", 2, buf2str(text), rb_align); + } } static void diff --git a/test/custom_render_test.rb b/test/custom_render_test.rb index 87c9f07c..d86ed353 100644 --- a/test/custom_render_test.rb +++ b/test/custom_render_test.rb @@ -64,4 +64,43 @@ def test_base_render_without_quote_callback assert_equal "", parser.render(%(a "quote")) end + + def test_table_cell_callback_having_either_two_or_three_args + two = Class.new(Redcarpet::Render::HTML) do + def table_cell(content, alignment) + %(#{content}) + end + end + + three = Class.new(Redcarpet::Render::HTML) do + def table_cell(content, alignment, header) + tag = header ? "th" : "td" + + %(<#{tag}>#{content}) + end + end + + markdown = <<-Md.chomp.strip_heredoc + | A | B | + |---|---| + | C | D | + Md + + first_parser = Redcarpet::Markdown.new(two.new, tables: true) + second_parser = Redcarpet::Markdown.new(three.new, tables: true) + + first_output = first_parser.render(markdown) + second_output = second_parser.render(markdown) + + assert { first_output.include?("A") } + assert { first_output.include?("B") } + + assert { second_output.include?("A") } + assert { second_output.include?("B") } + + [first_output, second_output].each do |output| + assert { output.include?("C") } + assert { output.include?("D") } + end + end end