diff --git a/lib/rdoc/generator/template/darkfish/css/rdoc.css b/lib/rdoc/generator/template/darkfish/css/rdoc.css index 35aff77fcb..221550a051 100644 --- a/lib/rdoc/generator/template/darkfish/css/rdoc.css +++ b/lib/rdoc/generator/template/darkfish/css/rdoc.css @@ -79,6 +79,25 @@ pre { border-radius: 0.2em; } +table { + margin: 0; + border-spacing: 0; + border-collapse: collapse; +} + +table tr th, table tr td { + padding: 0.2em 0.4em; + border: 1px solid #ccc; +} + +table tr th { + background-color: #eceaed; +} + +table tr:nth-child(even) td { + background-color: #f5f4f6; +} + /* @group Generic Classes */ .initially-hidden { diff --git a/lib/rdoc/markdown.kpeg b/lib/rdoc/markdown.kpeg index 8b78cdd114..6717cce132 100644 --- a/lib/rdoc/markdown.kpeg +++ b/lib/rdoc/markdown.kpeg @@ -506,6 +506,7 @@ Block = @BlankLine* ( BlockQuote | Verbatim | CodeFence + | Table | Note | Reference | HorizontalRule @@ -1195,6 +1196,23 @@ CodeFence = &{ github? } verbatim } +Table = &{ github? } + TableRow:header TableLine:line TableRow+:body + { table = RDoc::Markup::Table.new(header, line, body) } + +TableRow = < TableItem+:row > "|" @Newline + { row } +TableItem = "|" < (!"|" !@Newline .)+ > + { text.strip } + +TableLine = TableColumn+:line "|" @Newline + { line } +TableColumn = "|" < ( "-"+ ":"? | ":" "-"* ) > + { + text.start_with?(":") ? :left : + text.end_with?(":") ? :right : nil + } + DefinitionList = &{ definition_lists? } ( DefinitionListItem+:list ) { RDoc::Markup::List.new :NOTE, *list.flatten } diff --git a/lib/rdoc/markup.rb b/lib/rdoc/markup.rb index fd59fca314..92aed757cf 100644 --- a/lib/rdoc/markup.rb +++ b/lib/rdoc/markup.rb @@ -843,6 +843,7 @@ def convert input, formatter autoload :List, 'rdoc/markup/list' autoload :ListItem, 'rdoc/markup/list_item' autoload :Paragraph, 'rdoc/markup/paragraph' + autoload :Table, 'rdoc/markup/table' autoload :Raw, 'rdoc/markup/raw' autoload :Rule, 'rdoc/markup/rule' autoload :Verbatim, 'rdoc/markup/verbatim' diff --git a/lib/rdoc/markup/table.rb b/lib/rdoc/markup/table.rb new file mode 100644 index 0000000000..7bcb10aff3 --- /dev/null +++ b/lib/rdoc/markup/table.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true +## +# A section of table + +class RDoc::Markup::Table + attr_accessor :header, :align, :body + + def initialize header, align, body + @header, @align, @body = header, align, body + end + + def == other + self.class == other.class and + @header == other.header and + @align == other.align and + @body == other.body + end + + def accept visitor + visitor.accept_table @header, @body, @align + end + + def pretty_print q # :nodoc: + q.group 2, '[Table: ', ']' do + q.group 2, '[Head: ', ']' do + q.seplist @header.zip(@align) do |text, align| + q.pp text + if align + q.text ":" + q.breakable + q.text align.to_s + end + end + end + q.breakable + q.group 2, '[Body: ', ']' do + q.seplist @body do |body| + q.group 2, '[', ']' do + q.seplist body do |text| + q.pp text + end + end + end + end + end + end +end diff --git a/lib/rdoc/markup/to_html.rb b/lib/rdoc/markup/to_html.rb index 3b1b0e9d40..e2a00bd8a1 100644 --- a/lib/rdoc/markup/to_html.rb +++ b/lib/rdoc/markup/to_html.rb @@ -314,6 +314,29 @@ def accept_raw raw @res << raw.parts.join("\n") end + ## + # Adds +table+ to the output + + def accept_table header, body, aligns + @res << "\n\n\n\n" + header.zip(aligns) do |text, align| + @res << '' << CGI.escapeHTML(text) << "\n" + end + @res << "\n\n\n" + body.each do |row| + @res << "\n" + row.zip(aligns) do |text, align| + @res << '' << CGI.escapeHTML(text) << "\n" + end + @res << "\n" + end + @res << "\n
\n" + end + # :section: Utilities ## diff --git a/lib/rdoc/markup/to_joined_paragraph.rb b/lib/rdoc/markup/to_joined_paragraph.rb index 795f3f62ee..46e07c94ad 100644 --- a/lib/rdoc/markup/to_joined_paragraph.rb +++ b/lib/rdoc/markup/to_joined_paragraph.rb @@ -41,6 +41,7 @@ def accept_paragraph paragraph alias accept_raw ignore alias accept_rule ignore alias accept_verbatim ignore + alias accept_table ignore end diff --git a/lib/rdoc/markup/to_rdoc.rb b/lib/rdoc/markup/to_rdoc.rb index 81b16c4973..3cdf4fd08b 100644 --- a/lib/rdoc/markup/to_rdoc.rb +++ b/lib/rdoc/markup/to_rdoc.rb @@ -237,6 +237,34 @@ def accept_verbatim verbatim @res << "\n" end + ## + # Adds +table+ to the output + + def accept_table header, body, aligns + widths = header.zip(body) do |h, b| + [h.size, b.size].max + end + aligns = aligns.map do |a| + case a + when nil + :center + when :left + :ljust + when :right + :rjust + end + end + @res << header.zip(widths, aligns) do |h, w, a| + h.__send__(a, w) + end.join("|").rstrip << "\n" + @res << widths.map {|w| "-" * w }.join("|") << "\n" + body.each do |row| + @res << row.zip(widths, aligns) do |t, w, a| + t.__send__(a, w) + end.join("|").rstrip << "\n" + end + end + ## # Applies attribute-specific markup to +text+ using RDoc::AttributeManager diff --git a/lib/rdoc/markup/to_table_of_contents.rb b/lib/rdoc/markup/to_table_of_contents.rb index f68b90bcf6..eb8e8faa16 100644 --- a/lib/rdoc/markup/to_table_of_contents.rb +++ b/lib/rdoc/markup/to_table_of_contents.rb @@ -82,6 +82,7 @@ def suppressed? heading alias accept_list_item_end ignore alias accept_list_end_bullet ignore alias accept_list_start ignore + alias accept_table ignore # :startdoc: end diff --git a/test/rdoc/test_rdoc_markdown.rb b/test/rdoc/test_rdoc_markdown.rb index 9c7a406224..697a1c600d 100644 --- a/test/rdoc/test_rdoc_markdown.rb +++ b/test/rdoc/test_rdoc_markdown.rb @@ -1012,6 +1012,29 @@ def test_code_fence_with_unintended_array assert_equal expected, doc end + def test_gfm_table + doc = parse <<~MD + | | |compare-ruby|built-ruby| + |------|:----------------|-----------:|---------:| + |test | 1 | 11.618M| 10.757M| + | | | 1.08x| -| + |test | 10 | 1.849M| 1.723M| + | | | 1.07x| -| + MD + + head = ["", "", "compare-ruby", "built-ruby"] + align = [nil, :left, :right, :right] + body = [ + ["test", "1", "11.618M", "10.757M"], + ["", "", "1.08x", "-"], + ["test", "10", "1.849M", "1.723M"], + ["", "", "1.07x", "-"], + ] + expected = doc(@RM::Table.new(head, align, body)) + + assert_equal expected, doc + end + def parse text @parser.parse text end