"Fossies" - the Fresh Open Source Software Archive

Member "asciidoctor-2.0.10/test/tables_test.rb" (1 Jun 2019, 65287 Bytes) of package /linux/www/asciidoctor-2.0.10.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Ruby source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 # frozen_string_literal: true
    2 require_relative 'test_helper'
    3 
    4 context 'Tables' do
    5   context 'PSV' do
    6     test 'converts simple psv table' do
    7       input = <<~'EOS'
    8       |=======
    9       |A |B |C
   10       |a |b |c
   11       |1 |2 |3
   12       |=======
   13       EOS
   14       cells = [%w(A B C), %w(a b c), %w(1 2 3)]
   15       doc = document_from_string input, standalone: false
   16       table = doc.blocks[0]
   17       assert 100, table.columns.map {|col| col.attributes['colpcwidth'] }.reduce(:+)
   18       output = doc.convert
   19       assert_css 'table', output, 1
   20       assert_css 'table.tableblock.frame-all.grid-all.stretch', output, 1
   21       assert_css 'table > colgroup > col[style*="width: 33.3333%"]', output, 2
   22       assert_css 'table > colgroup > col:last-of-type[style*="width: 33.3334%"]', output, 1
   23       assert_css 'table tr', output, 3
   24       assert_css 'table > tbody > tr', output, 3
   25       assert_css 'table td', output, 9
   26       assert_css 'table > tbody > tr > td.tableblock.halign-left.valign-top > p.tableblock', output, 9
   27       cells.each_with_index do |row, rowi|
   28         assert_css "table > tbody > tr:nth-child(#{rowi + 1}) > td", output, row.size
   29         assert_css "table > tbody > tr:nth-child(#{rowi + 1}) > td > p", output, row.size
   30         row.each_with_index do |cell, celli|
   31           assert_xpath "(//tr)[#{rowi + 1}]/td[#{celli + 1}]/p[text()='#{cell}']", output, 1
   32         end
   33       end
   34     end
   35 
   36     test 'should add direction CSS class if float attribute is set on table' do
   37       input = <<~'EOS'
   38       [float=left]
   39       |=======
   40       |A |B |C
   41       |a |b |c
   42       |1 |2 |3
   43       |=======
   44       EOS
   45 
   46       output = convert_string_to_embedded input
   47       assert_css 'table.left', output, 1
   48     end
   49 
   50     test 'should set stripes class if stripes option is set' do
   51       input = <<~'EOS'
   52       [stripes=odd]
   53       |=======
   54       |A |B |C
   55       |a |b |c
   56       |1 |2 |3
   57       |=======
   58       EOS
   59 
   60       output = convert_string_to_embedded input
   61       assert_css 'table.stripes-odd', output, 1
   62     end
   63 
   64     test 'outputs a caption on simple psv table' do
   65       input = <<~'EOS'
   66       .Simple psv table
   67       |=======
   68       |A |B |C
   69       |a |b |c
   70       |1 |2 |3
   71       |=======
   72       EOS
   73       output = convert_string_to_embedded input
   74       assert_xpath '/table/caption[@class="title"][text()="Table 1. Simple psv table"]', output, 1
   75       assert_xpath '/table/caption/following-sibling::colgroup', output, 1
   76     end
   77 
   78     test 'only increments table counter for tables that have a title' do
   79       input = <<~'EOS'
   80       .First numbered table
   81       |=======
   82       |1 |2 |3
   83       |=======
   84 
   85       |=======
   86       |4 |5 |6
   87       |=======
   88 
   89       .Second numbered table
   90       |=======
   91       |7 |8 |9
   92       |=======
   93       EOS
   94       output = convert_string_to_embedded input
   95       assert_css 'table:root', output, 3
   96       assert_xpath '(/table)[1]/caption', output, 1
   97       assert_xpath '(/table)[1]/caption[text()="Table 1. First numbered table"]', output, 1
   98       assert_xpath '(/table)[2]/caption', output, 0
   99       assert_xpath '(/table)[3]/caption', output, 1
  100       assert_xpath '(/table)[3]/caption[text()="Table 2. Second numbered table"]', output, 1
  101     end
  102 
  103     test 'uses explicit caption in front of title in place of default caption and number' do
  104       input = <<~'EOS'
  105       [caption="All the Data. "]
  106       .Simple psv table
  107       |=======
  108       |A |B |C
  109       |a |b |c
  110       |1 |2 |3
  111       |=======
  112       EOS
  113       output = convert_string_to_embedded input
  114       assert_xpath '/table/caption[@class="title"][text()="All the Data. Simple psv table"]', output, 1
  115       assert_xpath '/table/caption/following-sibling::colgroup', output, 1
  116     end
  117 
  118     test 'disables caption when caption attribute on table is empty' do
  119       input = <<~'EOS'
  120       [caption=]
  121       .Simple psv table
  122       |=======
  123       |A |B |C
  124       |a |b |c
  125       |1 |2 |3
  126       |=======
  127       EOS
  128       output = convert_string_to_embedded input
  129       assert_xpath '/table/caption[@class="title"][text()="Simple psv table"]', output, 1
  130       assert_xpath '/table/caption/following-sibling::colgroup', output, 1
  131     end
  132 
  133     test 'disables caption when caption attribute on table is empty string' do
  134       input = <<~'EOS'
  135       [caption=""]
  136       .Simple psv table
  137       |=======
  138       |A |B |C
  139       |a |b |c
  140       |1 |2 |3
  141       |=======
  142       EOS
  143       output = convert_string_to_embedded input
  144       assert_xpath '/table/caption[@class="title"][text()="Simple psv table"]', output, 1
  145       assert_xpath '/table/caption/following-sibling::colgroup', output, 1
  146     end
  147 
  148     test 'disables caption on table when table-caption document attribute is unset' do
  149       input = <<~'EOS'
  150       :!table-caption:
  151 
  152       .Simple psv table
  153       |=======
  154       |A |B |C
  155       |a |b |c
  156       |1 |2 |3
  157       |=======
  158       EOS
  159       output = convert_string_to_embedded input
  160       assert_xpath '/table/caption[@class="title"][text()="Simple psv table"]', output, 1
  161       assert_xpath '/table/caption/following-sibling::colgroup', output, 1
  162     end
  163 
  164     test 'ignores escaped separators' do
  165       input = <<~'EOS'
  166       |===
  167       |A \| here| a \| there
  168       |===
  169       EOS
  170       output = convert_string_to_embedded input
  171       assert_css 'table', output, 1
  172       assert_css 'table > colgroup > col', output, 2
  173       assert_css 'table > tbody > tr', output, 1
  174       assert_css 'table > tbody > tr > td', output, 2
  175       assert_xpath '/table/tbody/tr/td[1]/p[text()="A | here"]', output, 1
  176       assert_xpath '/table/tbody/tr/td[2]/p[text()="a | there"]', output, 1
  177     end
  178 
  179     test 'preserves escaped delimiters at the end of the line' do
  180       input = <<~'EOS'
  181       [%header,cols="1,1"]
  182       |===
  183       |A |B\|
  184       |A1 |B1\|
  185       |A2 |B2\|
  186       |===
  187       EOS
  188       output = convert_string_to_embedded input
  189       assert_css 'table', output, 1
  190       assert_css 'table > colgroup > col', output, 2
  191       assert_css 'table > thead > tr', output, 1
  192       assert_css 'table > thead > tr:nth-child(1) > th', output, 2
  193       assert_xpath '/table/thead/tr[1]/th[2][text()="B|"]', output, 1
  194       assert_css 'table > tbody > tr', output, 2
  195       assert_css 'table > tbody > tr:nth-child(1) > td', output, 2
  196       assert_xpath '/table/tbody/tr[1]/td[2]/p[text()="B1|"]', output, 1
  197       assert_css 'table > tbody > tr:nth-child(2) > td', output, 2
  198       assert_xpath '/table/tbody/tr[2]/td[2]/p[text()="B2|"]', output, 1
  199     end
  200 
  201     test 'should treat trailing pipe as an empty cell' do
  202       input = <<~'EOS'
  203       |===
  204       |A1 |
  205       |B1 |B2
  206       |C1 |C2
  207       |===
  208       EOS
  209       output = convert_string_to_embedded input
  210       assert_css 'table', output, 1
  211       assert_css 'table > colgroup > col', output, 2
  212       assert_css 'table > tbody > tr', output, 3
  213       assert_xpath '/table/tbody/tr[1]/td', output, 2
  214       assert_xpath '/table/tbody/tr[1]/td[1]/p[text()="A1"]', output, 1
  215       assert_xpath '/table/tbody/tr[1]/td[2]/p', output, 0
  216       assert_xpath '/table/tbody/tr[2]/td[1]/p[text()="B1"]', output, 1
  217     end
  218 
  219     test 'should auto recover with warning if missing leading separator on first cell' do
  220       input = <<~'EOS'
  221       |===
  222       A | here| a | there
  223       | x
  224       | y
  225       | z
  226       | end
  227       |===
  228       EOS
  229       using_memory_logger do |logger|
  230         output = convert_string_to_embedded input
  231         assert_css 'table', output, 1
  232         assert_css 'table > tbody > tr', output, 2
  233         assert_css 'table > tbody > tr > td', output, 8
  234         assert_xpath '/table/tbody/tr[1]/td[1]/p[text()="A"]', output, 1
  235         assert_xpath '/table/tbody/tr[1]/td[2]/p[text()="here"]', output, 1
  236         assert_xpath '/table/tbody/tr[1]/td[3]/p[text()="a"]', output, 1
  237         assert_xpath '/table/tbody/tr[1]/td[4]/p[text()="there"]', output, 1
  238         assert_message logger, :ERROR, '<stdin>: line 2: table missing leading separator; recovering automatically', Hash
  239       end
  240     end
  241 
  242     test 'performs normal substitutions on cell content' do
  243       input = <<~'EOS'
  244       :show_title: Cool new show
  245       |===
  246       |{show_title} |Coming soon...
  247       |===
  248       EOS
  249       output = convert_string_to_embedded input
  250       assert_xpath '//tbody/tr/td[1]/p[text()="Cool new show"]', output, 1
  251       assert_xpath %(//tbody/tr/td[2]/p[text()='Coming soon#{decode_char 8230}#{decode_char 8203}']), output, 1
  252     end
  253 
  254     test 'should only substitute specialchars for literal table cells' do
  255       input = <<~'EOS'
  256       |===
  257       l|one
  258       *two*
  259       three
  260       <four>
  261       |===
  262       EOS
  263       output = convert_string_to_embedded input
  264       result = xmlnodes_at_xpath('/table//pre', output, 1)
  265       assert_equal %(<pre>one\n*two*\nthree\n&lt;four&gt;</pre>), result.to_s
  266     end
  267 
  268     test 'should preserving leading spaces but not leading newlines or trailing spaces in literal table cells' do
  269       # NOTE cannot use single-quoted heredoc because of https://github.com/jruby/jruby/issues/4260
  270       input = <<~EOS
  271       [cols=2*]
  272       |===
  273       l|
  274         one
  275         two
  276       three
  277 
  278         | normal
  279       |===
  280       EOS
  281       output = convert_string_to_embedded input
  282       result = xmlnodes_at_xpath('/table//pre', output, 1)
  283       assert_equal %(<pre>  one\n  two\nthree</pre>), result.to_s
  284     end
  285 
  286     test 'should ignore v table cell style' do
  287       # NOTE cannot use single-quoted heredoc because of https://github.com/jruby/jruby/issues/4260
  288       input = <<~EOS
  289       [cols=2*]
  290       |===
  291       v|
  292         one
  293         two
  294       three
  295 
  296         | normal
  297       |===
  298       EOS
  299       output = convert_string_to_embedded input
  300       result = xmlnodes_at_xpath('/table//p[@class="tableblock"]', output, 1)
  301       assert_equal %(<p class="tableblock">one\n  two\nthree</p>), result.to_s
  302     end
  303 
  304     test 'table and column width not assigned when autowidth option is specified' do
  305       input = <<~'EOS'
  306       [options="autowidth"]
  307       |=======
  308       |A |B |C
  309       |a |b |c
  310       |1 |2 |3
  311       |=======
  312       EOS
  313       output = convert_string_to_embedded input
  314       assert_css 'table', output, 1
  315       assert_css 'table.fit-content', output, 1
  316       assert_css 'table[style*="width"]', output, 0
  317       assert_css 'table colgroup col', output, 3
  318       assert_css 'table colgroup col[style*="width"]', output, 0
  319     end
  320 
  321     test 'does not assign column width for autowidth columns in HTML output' do
  322       input = <<~'EOS'
  323       [cols="15%,3*~"]
  324       |=======
  325       |A |B |C |D
  326       |a |b |c |d
  327       |1 |2 |3 |4
  328       |=======
  329       EOS
  330       doc = document_from_string input
  331       table_row0 = doc.blocks[0].rows.body[0]
  332       assert_equal 15, table_row0[0].attributes['width']
  333       assert_equal 15, table_row0[0].attributes['colpcwidth']
  334       refute_equal '', table_row0[0].attributes['autowidth-option']
  335       expected_pcwidths = { 1 => 28.3333, 2 => 28.3333, 3 => 28.3334 }
  336       (1..3).each do |i|
  337         assert_equal 28.3333, table_row0[i].attributes['width']
  338         assert_equal expected_pcwidths[i], table_row0[i].attributes['colpcwidth']
  339         assert_equal '', table_row0[i].attributes['autowidth-option']
  340       end
  341       output = doc.convert standalone: false
  342       assert_css 'table', output, 1
  343       assert_css 'table colgroup col', output, 4
  344       assert_css 'table colgroup col[style]', output, 1
  345       assert_css 'table colgroup col[style*="width: 15%"]', output, 1
  346     end
  347 
  348     test 'can assign autowidth to all columns even when table has a width' do
  349       input = <<~'EOS'
  350       [cols="4*~",width=50%]
  351       |=======
  352       |A |B |C |D
  353       |a |b |c |d
  354       |1 |2 |3 |4
  355       |=======
  356       EOS
  357       doc = document_from_string input
  358       table_row0 = doc.blocks[0].rows.body[0]
  359       (0..3).each do |i|
  360         assert_equal 25, table_row0[i].attributes['width']
  361         assert_equal 25, table_row0[i].attributes['colpcwidth']
  362         assert_equal '', table_row0[i].attributes['autowidth-option']
  363       end
  364       output = doc.convert standalone: false
  365       assert_css 'table', output, 1
  366       assert_css 'table[style*="width: 50%;"]', output, 1
  367       assert_css 'table colgroup col', output, 4
  368       assert_css 'table colgroup col[style]', output, 0
  369     end
  370 
  371     test 'equally distributes remaining column width to autowidth columns in DocBook output' do
  372       input = <<~'EOS'
  373       [cols="15%,3*~"]
  374       |=======
  375       |A |B |C |D
  376       |a |b |c |d
  377       |1 |2 |3 |4
  378       |=======
  379       EOS
  380       output = convert_string_to_embedded input, backend: 'docbook5'
  381       assert_css 'tgroup[cols="4"]', output, 1
  382       assert_css 'tgroup colspec', output, 4
  383       assert_css 'tgroup colspec[colwidth]', output, 4
  384       assert_css 'tgroup colspec[colwidth="15*"]', output, 1
  385       assert_css 'tgroup colspec[colwidth="28.3333*"]', output, 2
  386       assert_css 'tgroup colspec[colwidth="28.3334*"]', output, 1
  387     end
  388 
  389     test 'should compute column widths based on pagewidth when width is set on table in DocBook output' do
  390       input = <<~'EOS'
  391       :pagewidth: 500
  392 
  393       [width=50%]
  394       |=======
  395       |A |B |C |D
  396 
  397       |a |b |c |d
  398       |1 |2 |3 |4
  399       |=======
  400       EOS
  401       output = convert_string_to_embedded input, backend: 'docbook5'
  402       assert_css 'tgroup[cols="4"]', output, 1
  403       assert_css 'tgroup colspec', output, 4
  404       assert_css 'tgroup colspec[colwidth]', output, 4
  405       assert_css 'tgroup colspec[colwidth="62.5*"]', output, 4
  406     end
  407 
  408     test 'explicit table width is used even when autowidth option is specified' do
  409       input = <<~'EOS'
  410       [%autowidth,width=75%]
  411       |=======
  412       |A |B |C
  413       |a |b |c
  414       |1 |2 |3
  415       |=======
  416       EOS
  417       output = convert_string_to_embedded input
  418       assert_css 'table', output, 1
  419       assert_css 'table[style*="width"]', output, 1
  420       assert_css 'table colgroup col', output, 3
  421       assert_css 'table colgroup col[style*="width"]', output, 0
  422     end
  423 
  424     test 'first row sets number of columns when not specified' do
  425       input = <<~'EOS'
  426       |===
  427       |first |second |third |fourth
  428       |1 |2 |3
  429       |4
  430       |===
  431       EOS
  432       output = convert_string_to_embedded input
  433       assert_css 'table', output, 1
  434       assert_css 'table > colgroup > col', output, 4
  435       assert_css 'table > tbody > tr', output, 2
  436       assert_css 'table > tbody > tr:nth-child(1) > td', output, 4
  437       assert_css 'table > tbody > tr:nth-child(2) > td', output, 4
  438     end
  439 
  440     test 'colspec attribute using asterisk syntax sets number of columns' do
  441       input = <<~'EOS'
  442       [cols="3*"]
  443       |===
  444       |A |B |C |a |b |c |1 |2 |3
  445       |===
  446       EOS
  447       output = convert_string_to_embedded input
  448       assert_css 'table', output, 1
  449       assert_css 'table > tbody > tr', output, 3
  450     end
  451 
  452     test 'table with explicit column count can have multiple rows on a single line' do
  453       input = <<~'EOS'
  454       [cols="3*"]
  455       |===
  456       |one |two
  457       |1 |2 |a |b
  458       |===
  459       EOS
  460       output = convert_string_to_embedded input
  461       assert_css 'table', output, 1
  462       assert_css 'table > colgroup > col', output, 3
  463       assert_css 'table > tbody > tr', output, 2
  464     end
  465 
  466     test 'table with explicit deprecated colspec syntax can have multiple rows on a single line' do
  467       input = <<~'EOS'
  468       [cols="3"]
  469       |===
  470       |one |two
  471       |1 |2 |a |b
  472       |===
  473       EOS
  474       output = convert_string_to_embedded input
  475       assert_css 'table', output, 1
  476       assert_css 'table > colgroup > col', output, 3
  477       assert_css 'table > tbody > tr', output, 2
  478     end
  479 
  480     test 'columns are added for empty records in colspec attribute' do
  481       input = <<~'EOS'
  482       [cols="<,"]
  483       |===
  484       |one |two
  485       |1 |2 |a |b
  486       |===
  487       EOS
  488       output = convert_string_to_embedded input
  489       assert_css 'table', output, 1
  490       assert_css 'table > colgroup > col', output, 2
  491       assert_css 'table > tbody > tr', output, 3
  492     end
  493 
  494     test 'cols may be separated by semi-colon instead of comma' do
  495       input = <<~'EOS'
  496       [cols="1s;3m"]
  497       |===
  498       | strong
  499       | mono
  500       |===
  501       EOS
  502       output = convert_string_to_embedded input
  503       assert_css 'table', output, 1
  504       assert_css 'table > colgroup > col', output, 2
  505       assert_css 'col[style="width: 25%;"]', output, 1
  506       assert_css 'col[style="width: 75%;"]', output, 1
  507       assert_xpath '(//td)[1]//strong', output, 1
  508       assert_xpath '(//td)[2]//code', output, 1
  509     end
  510 
  511     test 'cols attribute may include spaces' do
  512       input = <<~'EOS'
  513       [cols=" 1, 1 "]
  514       |===
  515       |one |two |1 |2 |a |b
  516       |===
  517       EOS
  518       output = convert_string_to_embedded input
  519       assert_css 'table', output, 1
  520       assert_css 'table > colgroup > col', output, 2
  521       assert_css 'col[style="width: 50%;"]', output, 2
  522       assert_css 'table > tbody > tr', output, 3
  523     end
  524 
  525     test 'blank cols attribute should be ignored' do
  526       input = <<~'EOS'
  527       [cols=" "]
  528       |===
  529       |one |two
  530       |1 |2 |a |b
  531       |===
  532       EOS
  533       output = convert_string_to_embedded input
  534       assert_css 'table', output, 1
  535       assert_css 'table > colgroup > col', output, 2
  536       assert_css 'col[style="width: 50%;"]', output, 2
  537       assert_css 'table > tbody > tr', output, 3
  538     end
  539 
  540     test 'empty cols attribute should be ignored' do
  541       input = <<~'EOS'
  542       [cols=""]
  543       |===
  544       |one |two
  545       |1 |2 |a |b
  546       |===
  547       EOS
  548       output = convert_string_to_embedded input
  549       assert_css 'table', output, 1
  550       assert_css 'table > colgroup > col', output, 2
  551       assert_css 'col[style="width: 50%;"]', output, 2
  552       assert_css 'table > tbody > tr', output, 3
  553     end
  554 
  555     test 'table with header and footer' do
  556       input = <<~'EOS'
  557       [frame="topbot",options="header,footer"]
  558       |===
  559       |Item       |Quantity
  560       |Item 1     |1
  561       |Item 2     |2
  562       |Item 3     |3
  563       |Total      |6
  564       |===
  565       EOS
  566       output = convert_string_to_embedded input
  567       assert_css 'table', output, 1
  568       assert_css 'table > colgroup > col', output, 2
  569       assert_css 'table > thead', output, 1
  570       assert_css 'table > thead > tr', output, 1
  571       assert_css 'table > thead > tr > th', output, 2
  572       assert_css 'table > tfoot', output, 1
  573       assert_css 'table > tfoot > tr', output, 1
  574       assert_css 'table > tfoot > tr > td', output, 2
  575       assert_css 'table > tbody', output, 1
  576       assert_css 'table > tbody > tr', output, 3
  577       table_section_names = (xmlnodes_at_css 'table > *', output).map(&:node_name).select {|n| n.start_with? 't' }
  578       assert_equal %w(thead tbody tfoot), table_section_names
  579     end
  580 
  581     test 'table with header and footer docbook' do
  582       input = <<~'EOS'
  583       .Table with header, body and footer
  584       [frame="topbot",options="header,footer"]
  585       |===
  586       |Item       |Quantity
  587       |Item 1     |1
  588       |Item 2     |2
  589       |Item 3     |3
  590       |Total      |6
  591       |===
  592       EOS
  593       output = convert_string_to_embedded input, backend: 'docbook'
  594       assert_css 'table', output, 1
  595       assert_css 'table[frame="topbot"]', output, 1
  596       assert_css 'table > title', output, 1
  597       assert_css 'table > tgroup', output, 1
  598       assert_css 'table > tgroup[cols="2"]', output, 1
  599       assert_css 'table > tgroup[cols="2"] > colspec', output, 2
  600       assert_css 'table > tgroup[cols="2"] > colspec[colwidth="50*"]', output, 2
  601       assert_css 'table > tgroup > thead', output, 1
  602       assert_css 'table > tgroup > thead > row', output, 1
  603       assert_css 'table > tgroup > thead > row > entry', output, 2
  604       assert_css 'table > tgroup > thead > row > entry > simpara', output, 0
  605       assert_css 'table > tgroup > tfoot', output, 1
  606       assert_css 'table > tgroup > tfoot > row', output, 1
  607       assert_css 'table > tgroup > tfoot > row > entry', output, 2
  608       assert_css 'table > tgroup > tfoot > row > entry > simpara', output, 2
  609       assert_css 'table > tgroup > tbody', output, 1
  610       assert_css 'table > tgroup > tbody > row', output, 3
  611       assert_css 'table > tgroup > tbody > row', output, 3
  612       table_section_names = (xmlnodes_at_css 'table > tgroup > *', output).map(&:node_name).select {|n| n.start_with? 't' }
  613       assert_equal %w(thead tbody tfoot), table_section_names
  614     end
  615 
  616     test 'should recognize ends as an alias to topbot for frame when converting to DocBook' do
  617       input = <<~'EOS'
  618       [frame=ends]
  619       |===
  620       |A |B |C
  621       |===
  622       EOS
  623       output = convert_string_to_embedded input, backend: 'docbook'
  624       assert_css 'informaltable[frame="topbot"]', output, 1
  625     end
  626 
  627     test 'table with landscape orientation in DocBook' do
  628       ['orientation=landscape', '%rotate'].each do |attrs|
  629         input = <<~EOS
  630         [#{attrs}]
  631         |===
  632         |Column A | Column B | Column C
  633         |===
  634         EOS
  635 
  636         output = convert_string_to_embedded input, backend: 'docbook'
  637         assert_css 'informaltable', output, 1
  638         assert_css 'informaltable[orient="land"]', output, 1
  639       end
  640     end
  641 
  642     test 'table with implicit header row' do
  643       input = <<~'EOS'
  644       |===
  645       |Column 1 |Column 2
  646 
  647       |Data A1
  648       |Data B1
  649 
  650       |Data A2
  651       |Data B2
  652       |===
  653       EOS
  654       output = convert_string_to_embedded input
  655       assert_css 'table', output, 1
  656       assert_css 'table > colgroup > col', output, 2
  657       assert_css 'table > thead', output, 1
  658       assert_css 'table > thead > tr', output, 1
  659       assert_css 'table > thead > tr > th', output, 2
  660       assert_css 'table > tbody', output, 1
  661       assert_css 'table > tbody > tr', output, 2
  662     end
  663 
  664     test 'table with implicit header row only' do
  665       input = <<~'EOS'
  666       |===
  667       |Column 1 |Column 2
  668 
  669       |===
  670       EOS
  671       output = convert_string_to_embedded input
  672       assert_css 'table', output, 1
  673       assert_css 'table > colgroup > col', output, 2
  674       assert_css 'table > thead', output, 1
  675       assert_css 'table > thead > tr', output, 1
  676       assert_css 'table > thead > tr > th', output, 2
  677       assert_css 'table > tbody', output, 0
  678     end
  679 
  680     test 'table with implicit header row when other options set' do
  681       input = <<~'EOS'
  682       [%autowidth]
  683       |===
  684       |Column 1 |Column 2
  685 
  686       |Data A1
  687       |Data B1
  688       |===
  689       EOS
  690       output = convert_string_to_embedded input
  691       assert_css 'table', output, 1
  692       assert_css 'table[style*="width"]', output, 0
  693       assert_css 'table > colgroup > col', output, 2
  694       assert_css 'table > thead', output, 1
  695       assert_css 'table > thead > tr', output, 1
  696       assert_css 'table > thead > tr > th', output, 2
  697       assert_css 'table > tbody', output, 1
  698       assert_css 'table > tbody > tr', output, 1
  699     end
  700 
  701     test 'no implicit header row if second line not blank' do
  702       input = <<~'EOS'
  703       |===
  704       |Column 1 |Column 2
  705       |Data A1
  706       |Data B1
  707 
  708       |Data A2
  709       |Data B2
  710       |===
  711       EOS
  712       output = convert_string_to_embedded input
  713       assert_css 'table', output, 1
  714       assert_css 'table > colgroup > col', output, 2
  715       assert_css 'table > thead', output, 0
  716       assert_css 'table > tbody', output, 1
  717       assert_css 'table > tbody > tr', output, 3
  718     end
  719 
  720     test 'no implicit header row if cell in first line spans multiple lines' do
  721       input = <<~'EOS'
  722       [cols=2*]
  723       |===
  724       |A1
  725 
  726 
  727       A1 continued|B1
  728 
  729       |A2
  730       |B2
  731       |===
  732       EOS
  733       output = convert_string_to_embedded input
  734       assert_css 'table', output, 1
  735       assert_css 'table > colgroup > col', output, 2
  736       assert_css 'table > thead', output, 0
  737       assert_css 'table > tbody', output, 1
  738       assert_css 'table > tbody > tr', output, 2
  739       assert_xpath '(//td)[1]/p', output, 2
  740     end
  741 
  742     test 'no implicit header row if AsciiDoc cell in first line spans multiple lines' do
  743       input = <<~'EOS'
  744       [cols=2*]
  745       |===
  746       a|contains AsciiDoc content
  747 
  748       * a
  749       * b
  750       * c
  751       a|contains no AsciiDoc content
  752 
  753       just text
  754       |A2
  755       |B2
  756       |===
  757       EOS
  758       output = convert_string_to_embedded input
  759       assert_css 'table', output, 1
  760       assert_css 'table > colgroup > col', output, 2
  761       assert_css 'table > thead', output, 0
  762       assert_css 'table > tbody', output, 1
  763       assert_css 'table > tbody > tr', output, 2
  764       assert_xpath '(//td)[1]//ul', output, 1
  765     end
  766 
  767     test 'no implicit header row if first line blank' do
  768       input = <<~'EOS'
  769       |===
  770 
  771       |Column 1 |Column 2
  772 
  773       |Data A1
  774       |Data B1
  775 
  776       |Data A2
  777       |Data B2
  778 
  779       |===
  780       EOS
  781       output = convert_string_to_embedded input
  782       assert_css 'table', output, 1
  783       assert_css 'table > colgroup > col', output, 2
  784       assert_css 'table > thead', output, 0
  785       assert_css 'table > tbody', output, 1
  786       assert_css 'table > tbody > tr', output, 3
  787     end
  788 
  789     test 'no implicit header row if noheader option is specified' do
  790       input = <<~'EOS'
  791       [%noheader]
  792       |===
  793       |Column 1 |Column 2
  794 
  795       |Data A1
  796       |Data B1
  797 
  798       |Data A2
  799       |Data B2
  800       |===
  801       EOS
  802       output = convert_string_to_embedded input
  803       assert_css 'table', output, 1
  804       assert_css 'table > colgroup > col', output, 2
  805       assert_css 'table > thead', output, 0
  806       assert_css 'table > tbody', output, 1
  807       assert_css 'table > tbody > tr', output, 3
  808     end
  809 
  810     test 'styles not applied to header cells' do
  811       input = <<~'EOS'
  812       [cols="1h,1s,1e",options="header,footer"]
  813       |===
  814       |Name |Occupation| Website
  815       |Octocat |Social coding| https://github.com
  816       |Name |Occupation| Website
  817       |===
  818       EOS
  819       output = convert_string_to_embedded input
  820       assert_css 'table', output, 1
  821       assert_css 'table > thead > tr > th', output, 3
  822       assert_css 'table > thead > tr > th > *', output, 0
  823 
  824       assert_css 'table > tfoot > tr > th', output, 1
  825       assert_css 'table > tfoot > tr > td', output, 2
  826       assert_css 'table > tfoot > tr > td > p > strong', output, 1
  827       assert_css 'table > tfoot > tr > td > p > em', output, 1
  828 
  829       assert_css 'table > tbody > tr > th', output, 1
  830       assert_css 'table > tbody > tr > td', output, 2
  831       assert_css 'table > tbody > tr > td > p.header', output, 0
  832       assert_css 'table > tbody > tr > td > p > strong', output, 1
  833       assert_css 'table > tbody > tr > td > p > em > a', output, 1
  834     end
  835 
  836     test 'vertical table headers use th element instead of header class' do
  837       input = <<~'EOS'
  838       [cols="1h,1s,1e"]
  839       |===
  840 
  841       |Name |Occupation| Website
  842 
  843       |Octocat |Social coding| https://github.com
  844 
  845       |Name |Occupation| Website
  846 
  847       |===
  848       EOS
  849       output = convert_string_to_embedded input
  850       assert_css 'table', output, 1
  851       assert_css 'table > tbody > tr > th', output, 3
  852       assert_css 'table > tbody > tr > td', output, 6
  853       assert_css 'table > tbody > tr .header', output, 0
  854       assert_css 'table > tbody > tr > td > p > strong', output, 3
  855       assert_css 'table > tbody > tr > td > p > em', output, 3
  856       assert_css 'table > tbody > tr > td > p > em > a', output, 1
  857     end
  858 
  859     test 'supports horizontal and vertical source data with blank lines and table header' do
  860       input = <<~'EOS'
  861       .Horizontal and vertical source data
  862       [width="80%",cols="3,^2,^2,10",options="header"]
  863       |===
  864       |Date |Duration |Avg HR |Notes
  865 
  866       |22-Aug-08 |10:24 | 157 |
  867       Worked out MSHR (max sustainable heart rate) by going hard
  868       for this interval.
  869 
  870       |22-Aug-08 |23:03 | 152 |
  871       Back-to-back with previous interval.
  872 
  873       |24-Aug-08 |40:00 | 145 |
  874       Moderately hard interspersed with 3x 3min intervals (2 min
  875       hard + 1 min really hard taking the HR up to 160).
  876 
  877       I am getting in shape!
  878 
  879       |===
  880       EOS
  881       output = convert_string_to_embedded input
  882       assert_css 'table', output, 1
  883       assert_css 'table[style*="width: 80%"]', output, 1
  884       assert_xpath '/table/caption[@class="title"][text()="Table 1. Horizontal and vertical source data"]', output, 1
  885       assert_css 'table > colgroup > col', output, 4
  886       assert_css 'table > colgroup > col:nth-child(1)[@style*="width: 17.647%"]', output, 1
  887       assert_css 'table > colgroup > col:nth-child(2)[@style*="width: 11.7647%"]', output, 1
  888       assert_css 'table > colgroup > col:nth-child(3)[@style*="width: 11.7647%"]', output, 1
  889       assert_css 'table > colgroup > col:nth-child(4)[@style*="width: 58.8236%"]', output, 1
  890       assert_css 'table > thead', output, 1
  891       assert_css 'table > thead > tr', output, 1
  892       assert_css 'table > thead > tr > th', output, 4
  893       assert_css 'table > tbody > tr', output, 3
  894       assert_css 'table > tbody > tr:nth-child(1) > td', output, 4
  895       assert_css 'table > tbody > tr:nth-child(2) > td', output, 4
  896       assert_css 'table > tbody > tr:nth-child(3) > td', output, 4
  897       assert_xpath "/table/tbody/tr[1]/td[4]/p[text()='Worked out MSHR (max sustainable heart rate) by going hard\nfor this interval.']", output, 1
  898       assert_css 'table > tbody > tr:nth-child(3) > td:nth-child(4) > p', output, 2
  899       assert_xpath '/table/tbody/tr[3]/td[4]/p[2][text()="I am getting in shape!"]', output, 1
  900     end
  901 
  902     test 'percentages as column widths' do
  903       input = <<~'EOS'
  904       [cols="<.^10%,<90%"]
  905       |===
  906       |column A |column B
  907       |===
  908       EOS
  909 
  910       output = convert_string_to_embedded input
  911       assert_xpath '/table/colgroup/col', output, 2
  912       assert_xpath '(/table/colgroup/col)[1][@style="width: 10%;"]', output, 1
  913       assert_xpath '(/table/colgroup/col)[2][@style="width: 90%;"]', output, 1
  914     end
  915 
  916     test 'spans, alignments and styles' do
  917       input = <<~'EOS'
  918       [cols="e,m,^,>s",width="25%"]
  919       |===
  920       |1 >s|2 |3 |4
  921       ^|5 2.2+^.^|6 .3+<.>m|7
  922       ^|8
  923       d|9 2+>|10
  924       |===
  925       EOS
  926       output = convert_string_to_embedded input
  927       assert_css 'table', output, 1
  928       assert_css 'table > colgroup > col[style*="width: 25%"]', output, 4
  929       assert_css 'table > tbody > tr', output, 4
  930       assert_css 'table > tbody > tr > td', output, 10
  931       assert_css 'table > tbody > tr:nth-child(1) > td', output, 4
  932       assert_css 'table > tbody > tr:nth-child(2) > td', output, 3
  933       assert_css 'table > tbody > tr:nth-child(3) > td', output, 1
  934       assert_css 'table > tbody > tr:nth-child(4) > td', output, 2
  935 
  936       assert_css 'table > tbody > tr:nth-child(1) > td:nth-child(1).halign-left.valign-top p em', output, 1
  937       assert_css 'table > tbody > tr:nth-child(1) > td:nth-child(2).halign-right.valign-top p strong', output, 1
  938       assert_css 'table > tbody > tr:nth-child(1) > td:nth-child(3).halign-center.valign-top p', output, 1
  939       assert_css 'table > tbody > tr:nth-child(1) > td:nth-child(3).halign-center.valign-top p *', output, 0
  940       assert_css 'table > tbody > tr:nth-child(1) > td:nth-child(4).halign-right.valign-top p strong', output, 1
  941 
  942       assert_css 'table > tbody > tr:nth-child(2) > td:nth-child(1).halign-center.valign-top p em', output, 1
  943       assert_css 'table > tbody > tr:nth-child(2) > td:nth-child(2).halign-center.valign-middle[colspan="2"][rowspan="2"] p code', output, 1
  944       assert_css 'table > tbody > tr:nth-child(2) > td:nth-child(3).halign-left.valign-bottom[rowspan="3"] p code', output, 1
  945 
  946       assert_css 'table > tbody > tr:nth-child(3) > td:nth-child(1).halign-center.valign-top p em', output, 1
  947 
  948       assert_css 'table > tbody > tr:nth-child(4) > td:nth-child(1).halign-left.valign-top p', output, 1
  949       assert_css 'table > tbody > tr:nth-child(4) > td:nth-child(1).halign-left.valign-top p em', output, 0
  950       assert_css 'table > tbody > tr:nth-child(4) > td:nth-child(2).halign-right.valign-top[colspan="2"] p code', output, 1
  951     end
  952 
  953     test 'sets up columns correctly if first row has cell that spans columns' do
  954       input = <<~'EOS'
  955       |===
  956       2+^|AAA |CCC
  957       |AAA |BBB |CCC
  958       |AAA |BBB |CCC
  959       |===
  960       EOS
  961       output = convert_string_to_embedded input
  962       assert_css 'table > tbody > tr:nth-child(1) > td', output, 2
  963       assert_css 'table > tbody > tr:nth-child(1) > td:nth-child(1)[colspan="2"]', output, 1
  964       assert_css 'table > tbody > tr:nth-child(1) > td:nth-child(2):not([colspan])', output, 1
  965       assert_css 'table > tbody > tr:nth-child(2) > td:not([colspan])', output, 3
  966       assert_css 'table > tbody > tr:nth-child(3) > td:not([colspan])', output, 3
  967     end
  968 
  969     test 'supports repeating cells' do
  970       input = <<~'EOS'
  971       |===
  972       3*|A
  973       |1 3*|2
  974       |b |c
  975       |===
  976       EOS
  977       output = convert_string_to_embedded input
  978       assert_css 'table', output, 1
  979       assert_css 'table > colgroup > col', output, 3
  980       assert_css 'table > tbody > tr', output, 3
  981       assert_css 'table > tbody > tr:nth-child(1) > td', output, 3
  982       assert_css 'table > tbody > tr:nth-child(2) > td', output, 3
  983       assert_css 'table > tbody > tr:nth-child(3) > td', output, 3
  984 
  985       assert_xpath '/table/tbody/tr[1]/td[1]/p[text()="A"]', output, 1
  986       assert_xpath '/table/tbody/tr[1]/td[2]/p[text()="A"]', output, 1
  987       assert_xpath '/table/tbody/tr[1]/td[3]/p[text()="A"]', output, 1
  988 
  989       assert_xpath '/table/tbody/tr[2]/td[1]/p[text()="1"]', output, 1
  990       assert_xpath '/table/tbody/tr[2]/td[2]/p[text()="2"]', output, 1
  991       assert_xpath '/table/tbody/tr[2]/td[3]/p[text()="2"]', output, 1
  992 
  993       assert_xpath '/table/tbody/tr[3]/td[1]/p[text()="2"]', output, 1
  994       assert_xpath '/table/tbody/tr[3]/td[2]/p[text()="b"]', output, 1
  995       assert_xpath '/table/tbody/tr[3]/td[3]/p[text()="c"]', output, 1
  996     end
  997 
  998     test 'calculates colnames correctly when using implicit column count and single cell with colspan' do
  999       input = <<~'EOS'
 1000       |===
 1001       2+|Two Columns
 1002       |One Column |One Column
 1003       |===
 1004       EOS
 1005 
 1006       output = convert_string_to_embedded input, backend: 'docbook'
 1007       assert_xpath '//colspec', output, 2
 1008       assert_xpath '(//colspec)[1][@colname="col_1"]', output, 1
 1009       assert_xpath '(//colspec)[2][@colname="col_2"]', output, 1
 1010       assert_xpath '//row', output, 2
 1011       assert_xpath '(//row)[1]/entry', output, 1
 1012       assert_xpath '(//row)[1]/entry[@namest="col_1"][@nameend="col_2"]', output, 1
 1013     end
 1014 
 1015     test 'calculates colnames correctly when using implicit column count and cells with mixed colspans' do
 1016       input = <<~'EOS'
 1017       |===
 1018       2+|Two Columns | One Column
 1019       |One Column |One Column |One Column
 1020       |===
 1021       EOS
 1022 
 1023       output = convert_string_to_embedded input, backend: 'docbook'
 1024       assert_xpath '//colspec', output, 3
 1025       assert_xpath '(//colspec)[1][@colname="col_1"]', output, 1
 1026       assert_xpath '(//colspec)[2][@colname="col_2"]', output, 1
 1027       assert_xpath '(//colspec)[3][@colname="col_3"]', output, 1
 1028       assert_xpath '//row', output, 2
 1029       assert_xpath '(//row)[1]/entry', output, 2
 1030       assert_xpath '(//row)[1]/entry[@namest="col_1"][@nameend="col_2"]', output, 1
 1031       assert_xpath '(//row)[2]/entry[@namest]', output, 0
 1032       assert_xpath '(//row)[2]/entry[@nameend]', output, 0
 1033     end
 1034 
 1035     test 'assigns unique column names for table with implicit column count and colspans in first row' do
 1036       input = <<~'EOS'
 1037       |===
 1038       |                 2+| Node 0          2+| Node 1
 1039 
 1040       | Host processes    | Core 0 | Core 1   | Core 4 | Core 5
 1041       | Guest processes   | Core 2 | Core 3   | Core 6 | Core 7
 1042       |===
 1043       EOS
 1044 
 1045       output = convert_string_to_embedded input, backend: 'docbook'
 1046       assert_xpath '//colspec', output, 5
 1047       (1..5).each do |n|
 1048         assert_xpath %((//colspec)[#{n}][@colname="col_#{n}"]), output, 1
 1049       end
 1050       assert_xpath '(//row)[1]/entry', output, 3
 1051       assert_xpath '((//row)[1]/entry)[1][@namest]', output, 0
 1052       assert_xpath '((//row)[1]/entry)[1][@namend]', output, 0
 1053       assert_xpath '((//row)[1]/entry)[2][@namest="col_2"][@nameend="col_3"]', output, 1
 1054       assert_xpath '((//row)[1]/entry)[3][@namest="col_4"][@nameend="col_5"]', output, 1
 1055     end
 1056 
 1057     test 'ignores cell with colspan that exceeds colspec' do
 1058       input = <<~'EOS'
 1059       [cols=2*]
 1060       |===
 1061       3+|A
 1062       |B
 1063       a|C
 1064 
 1065       more C
 1066       |===
 1067       EOS
 1068       using_memory_logger do |logger|
 1069         output = convert_string_to_embedded input
 1070         assert_css 'table', output, 1
 1071         assert_css 'table *', output, 0
 1072         assert_message logger, :ERROR, '<stdin>: line 5: dropping cell because it exceeds specified number of columns', Hash
 1073       end
 1074     end
 1075 
 1076     test 'paragraph and literal repeated content' do
 1077       input = <<~'EOS'
 1078       [cols=",^l"]
 1079       |===
 1080       |Paragraphs |Literal
 1081 
 1082       3*|The discussion about what is good,
 1083       what is beautiful, what is noble,
 1084       what is pure, and what is true
 1085       could always go on.
 1086 
 1087       Why is that important?
 1088       Why would I like to do that?
 1089 
 1090       Because that's the only conversation worth having.
 1091 
 1092       And whether it goes on or not after I die, I don't know.
 1093       But, I do know that it is the conversation I want to have while I am still alive.
 1094 
 1095       Which means that to me the offer of certainty,
 1096       the offer of complete security,
 1097       the offer of an impermeable faith that can't give way
 1098       is an offer of something not worth having.
 1099 
 1100       I want to live my life taking the risk all the time
 1101       that I don't know anything like enough yet...
 1102       that I haven't understood enough...
 1103       that I can't know enough...
 1104       that I am always hungrily operating on the margins
 1105       of a potentially great harvest of future knowledge and wisdom.
 1106 
 1107       I wouldn't have it any other way.
 1108       |===
 1109       EOS
 1110       output = convert_string_to_embedded input
 1111       assert_css 'table', output, 1
 1112       assert_css 'table > colgroup > col', output, 2
 1113       assert_css 'table > thead', output, 1
 1114       assert_css 'table > thead > tr', output, 1
 1115       assert_css 'table > thead > tr > th', output, 2
 1116       assert_css 'table > tbody', output, 1
 1117       assert_css 'table > tbody > tr', output, 1
 1118       assert_css 'table > tbody > tr > td', output, 2
 1119       assert_css 'table > tbody > tr > td:nth-child(1).halign-left.valign-top > p.tableblock', output, 7
 1120       assert_css 'table > tbody > tr > td:nth-child(2).halign-center.valign-top > div.literal > pre', output, 1
 1121       literal = xmlnodes_at_css 'table > tbody > tr > td:nth-child(2).halign-center.valign-top > div.literal > pre', output, 1
 1122       assert_equal 26, literal.text.lines.size
 1123     end
 1124 
 1125     test 'should not split paragraph at line containing only {blank} that is directly adjacent to non-blank lines' do
 1126       input = <<~'EOS'
 1127       |===
 1128       |paragraph
 1129       {blank}
 1130       still one paragraph
 1131       {blank}
 1132       still one paragraph
 1133       |===
 1134       EOS
 1135 
 1136       result = convert_string_to_embedded input
 1137       assert_css 'p.tableblock', result, 1
 1138     end
 1139 
 1140     test 'should strip trailing newlines when splitting paragraphs' do
 1141       input = <<~'EOS'
 1142       |===
 1143       |first wrapped
 1144       paragraph
 1145 
 1146       second paragraph
 1147 
 1148       third paragraph
 1149       |===
 1150       EOS
 1151 
 1152       result = convert_string_to_embedded input
 1153       assert_xpath %((//p[@class="tableblock"])[1][text()="first wrapped\nparagraph"]), result, 1
 1154       assert_xpath %((//p[@class="tableblock"])[2][text()="second paragraph"]), result, 1
 1155       assert_xpath %((//p[@class="tableblock"])[3][text()="third paragraph"]), result, 1
 1156     end
 1157 
 1158     test 'basic AsciiDoc cell' do
 1159       input = <<~'EOS'
 1160       |===
 1161       a|--
 1162       NOTE: content
 1163 
 1164       content
 1165       --
 1166       |===
 1167       EOS
 1168 
 1169       result = convert_string_to_embedded input
 1170       assert_css 'table.tableblock', result, 1
 1171       assert_css 'table.tableblock td.tableblock', result, 1
 1172       assert_css 'table.tableblock td.tableblock .openblock', result, 1
 1173       assert_css 'table.tableblock td.tableblock .openblock .admonitionblock', result, 1
 1174       assert_css 'table.tableblock td.tableblock .openblock .paragraph', result, 1
 1175     end
 1176 
 1177     test 'AsciiDoc table cell should be wrapped in div with class "content"' do
 1178       input = <<~'EOS'
 1179       |===
 1180       a|AsciiDoc table cell
 1181       |===
 1182       EOS
 1183 
 1184       result = convert_string_to_embedded input
 1185       assert_css 'table.tableblock td.tableblock > div.content', result, 1
 1186       assert_css 'table.tableblock td.tableblock > div.content > div.paragraph', result, 1
 1187     end
 1188 
 1189     test 'doctype can be set in AsciiDoc table cell' do
 1190       input = <<~'EOS'
 1191       |===
 1192       a|
 1193       :doctype: inline
 1194 
 1195       content
 1196       |===
 1197       EOS
 1198 
 1199       result = convert_string_to_embedded input
 1200       assert_css 'table.tableblock', result, 1
 1201       assert_css 'table.tableblock .paragraph', result, 0
 1202     end
 1203 
 1204     test 'should reset doctype to default in AsciiDoc table cell' do
 1205       input = <<~'EOS'
 1206       = Book Title
 1207       :doctype: book
 1208 
 1209       == Chapter 1
 1210 
 1211       |===
 1212       a|
 1213       = AsciiDoc Table Cell
 1214 
 1215       doctype={doctype}
 1216       {backend-html5-doctype-article}
 1217       {backend-html5-doctype-book}
 1218       |===
 1219       EOS
 1220 
 1221       result = convert_string_to_embedded input, attributes: { 'attribute-missing' => 'skip' }
 1222       assert_includes result, 'doctype=article'
 1223       refute_includes result, '{backend-html5-doctype-article}'
 1224       assert_includes result, '{backend-html5-doctype-book}'
 1225     end
 1226 
 1227     test 'should update doctype-related attributes in AsciiDoc table cell when doctype is set' do
 1228       input = <<~'EOS'
 1229       = Document Title
 1230       :doctype: article
 1231 
 1232       == Chapter 1
 1233 
 1234       |===
 1235       a|
 1236       = AsciiDoc Table Cell
 1237       :doctype: book
 1238 
 1239       doctype={doctype}
 1240       {backend-html5-doctype-book}
 1241       {backend-html5-doctype-article}
 1242       |===
 1243       EOS
 1244 
 1245       result = convert_string_to_embedded input, attributes: { 'attribute-missing' => 'skip' }
 1246       assert_includes result, 'doctype=book'
 1247       refute_includes result, '{backend-html5-doctype-book}'
 1248       assert_includes result, '{backend-html5-doctype-article}'
 1249     end
 1250 
 1251     test 'AsciiDoc content' do
 1252       input = <<~'EOS'
 1253       [cols="1e,1,5a",frame="topbot",options="header"]
 1254       |===
 1255       |Name |Backends |Description
 1256 
 1257       |badges |xhtml11, html5 |
 1258       Link badges ('XHTML 1.1' and 'CSS') in document footers.
 1259 
 1260       [NOTE]
 1261       ====
 1262       The path names of images, icons and scripts are relative path
 1263       names to the output document not the source document.
 1264       ====
 1265       |[[X97]] docinfo, docinfo1, docinfo2 |All backends |
 1266       These three attributes control which document information
 1267       files will be included in the the header of the output file:
 1268 
 1269       docinfo:: Include `<filename>-docinfo.<ext>`
 1270       docinfo1:: Include `docinfo.<ext>`
 1271       docinfo2:: Include `docinfo.<ext>` and `<filename>-docinfo.<ext>`
 1272 
 1273       Where `<filename>` is the file name (sans extension) of the AsciiDoc
 1274       input file and `<ext>` is `.html` for HTML outputs or `.xml` for
 1275       DocBook outputs. If the input file is the standard input then the
 1276       output file name is used.
 1277       |===
 1278       EOS
 1279       doc = document_from_string input, sourcemap: true
 1280       table = doc.blocks.first
 1281       refute_nil table
 1282       tbody = table.rows.body
 1283       assert_equal 2, tbody.size
 1284       body_cell_1_2 = tbody[0][1]
 1285       assert_equal 5, body_cell_1_2.lineno
 1286       body_cell_1_3 = tbody[0][2]
 1287       refute_nil body_cell_1_3.inner_document
 1288       assert body_cell_1_3.inner_document.nested?
 1289       assert_equal doc, body_cell_1_3.inner_document.parent_document
 1290       assert_equal doc.converter, body_cell_1_3.inner_document.converter
 1291       assert_equal 5, body_cell_1_3.lineno
 1292       assert_equal 6, body_cell_1_3.inner_document.lineno
 1293       note = (body_cell_1_3.inner_document.find_by context: :admonition)[0]
 1294       assert_equal 9, note.lineno
 1295       output = doc.convert standalone: false
 1296 
 1297       # NOTE JRuby matches the table inside the admonition block if the class is not specified on the table
 1298       assert_css 'table.tableblock > tbody > tr', output, 2
 1299       assert_css 'table.tableblock > tbody > tr:nth-child(1) > td:nth-child(3) div.admonitionblock', output, 1
 1300       assert_css 'table.tableblock > tbody > tr:nth-child(2) > td:nth-child(3) div.dlist', output, 1
 1301     end
 1302 
 1303     test 'should preserve leading indentation in contents of AsciiDoc table cell if contents starts with newline' do
 1304       # NOTE cannot use single-quoted heredoc because of https://github.com/jruby/jruby/issues/4260
 1305       input = <<~EOS
 1306       |===
 1307       a|
 1308        $ command
 1309       a| paragraph
 1310       |===
 1311       EOS
 1312       doc = document_from_string input, sourcemap: true
 1313       table = doc.blocks[0]
 1314       tbody = table.rows.body
 1315       assert_equal 1, table.lineno
 1316       assert_equal 2, tbody[0][0].lineno
 1317       assert_equal 3, tbody[0][0].inner_document.lineno
 1318       assert_equal 4, tbody[1][0].lineno
 1319       output = doc.convert standalone: false
 1320       assert_css 'td', output, 2
 1321       assert_xpath '(//td)[1]//*[@class="literalblock"]', output, 1
 1322       assert_xpath '(//td)[2]//*[@class="paragraph"]', output, 1
 1323       assert_xpath '(//pre)[1][text()="$ command"]', output, 1
 1324       assert_xpath '(//p)[1][text()="paragraph"]', output, 1
 1325     end
 1326 
 1327     test 'preprocessor directive on first line of an AsciiDoc table cell should be processed' do
 1328       input = <<~'EOS'
 1329       |===
 1330       a|include::fixtures/include-file.adoc[]
 1331       |===
 1332       EOS
 1333 
 1334       output = convert_string_to_embedded input, safe: :safe, base_dir: testdir
 1335       assert_match(/included content/, output)
 1336     end
 1337 
 1338     test 'cross reference link in an AsciiDoc table cell should resolve to reference in main document' do
 1339       input = <<~'EOS'
 1340       == Some
 1341 
 1342       |===
 1343       a|See <<_more>>
 1344       |===
 1345 
 1346       == More
 1347 
 1348       content
 1349       EOS
 1350 
 1351       result = convert_string input
 1352       assert_xpath '//a[@href="#_more"]', result, 1
 1353       assert_xpath '//a[@href="#_more"][text()="More"]', result, 1
 1354     end
 1355 
 1356     test 'should discover anchor at start of cell and register it as a reference' do
 1357       input = <<~'EOS'
 1358       The highest peak in the Front Range is <<grays-peak>>, which tops <<mount-evans>> by just a few feet.
 1359 
 1360       [cols="1s,1"]
 1361       |===
 1362       |[[mount-evans,Mount Evans]]Mount Evans
 1363       |14,271 feet
 1364 
 1365       h|[[grays-peak,Grays Peak]]
 1366       Grays Peak
 1367       |14,278 feet
 1368       |===
 1369       EOS
 1370       doc = document_from_string input
 1371       refs = doc.catalog[:refs]
 1372       assert refs.key?('mount-evans')
 1373       assert refs.key?('grays-peak')
 1374       output = doc.convert standalone: false
 1375       assert_xpath '(//p)[1]/a[@href="#grays-peak"][text()="Grays Peak"]', output, 1
 1376       assert_xpath '(//p)[1]/a[@href="#mount-evans"][text()="Mount Evans"]', output, 1
 1377       assert_xpath '(//table/tbody/tr)[1]//td//a[@id="mount-evans"]', output, 1
 1378       assert_xpath '(//table/tbody/tr)[2]//th//a[@id="grays-peak"]', output, 1
 1379     end
 1380 
 1381     test 'footnotes should not be shared between an AsciiDoc table cell and the main document' do
 1382       input = <<~'EOS'
 1383       |===
 1384       a|AsciiDoc footnote:[A lightweight markup language.]
 1385       |===
 1386       EOS
 1387 
 1388       result = convert_string input
 1389       assert_css '#_footnotedef_1', result, 1
 1390     end
 1391 
 1392     test 'callout numbers should be globally unique, including AsciiDoc table cells' do
 1393       input = <<~'EOS'
 1394       = Document Title
 1395 
 1396       == Section 1
 1397 
 1398       |===
 1399       a|
 1400       [source, yaml]
 1401       ----
 1402       key: value <1>
 1403       ----
 1404       <1> First callout
 1405       |===
 1406 
 1407       == Section 2
 1408 
 1409       |===
 1410       a|
 1411       [source, yaml]
 1412       ----
 1413       key: value <1>
 1414       ----
 1415       <1> Second callout
 1416       |===
 1417 
 1418       == Section 3
 1419 
 1420       [source, yaml]
 1421       ----
 1422       key: value <1>
 1423       ----
 1424       <1> Third callout
 1425       EOS
 1426 
 1427       result = convert_string_to_embedded input, backend: 'docbook'
 1428       conums = xmlnodes_at_xpath '//co', result
 1429       assert_equal 3, conums.size
 1430       ['CO1-1', 'CO2-1', 'CO3-1'].each_with_index do |conum, idx|
 1431         assert_equal conum, conums[idx].attribute('xml:id').value
 1432       end
 1433       callouts = xmlnodes_at_xpath '//callout', result
 1434       assert_equal 3, callouts.size
 1435       ['CO1-1', 'CO2-1', 'CO3-1'].each_with_index do |callout, idx|
 1436         assert_equal callout, callouts[idx].attribute('arearefs').value
 1437       end
 1438     end
 1439 
 1440     test 'compat mode can be activated in AsciiDoc table cell' do
 1441       input = <<~'EOS'
 1442       |===
 1443       a|
 1444       :compat-mode:
 1445 
 1446       The word 'italic' is emphasized.
 1447       |===
 1448       EOS
 1449 
 1450       result = convert_string_to_embedded input
 1451       assert_xpath '//em[text()="italic"]', result, 1
 1452     end
 1453 
 1454     test 'compat mode in AsciiDoc table cell inherits from parent document' do
 1455       input = <<~'EOS'
 1456       :compat-mode:
 1457 
 1458       The word 'italic' is emphasized.
 1459 
 1460       [cols=1*]
 1461       |===
 1462       |The word 'oblique' is emphasized.
 1463       a|
 1464       The word 'slanted' is emphasized.
 1465       |===
 1466 
 1467       The word 'askew' is emphasized.
 1468       EOS
 1469 
 1470       result = convert_string_to_embedded input
 1471       assert_xpath '//em[text()="italic"]', result, 1
 1472       assert_xpath '//em[text()="oblique"]', result, 1
 1473       assert_xpath '//em[text()="slanted"]', result, 1
 1474       assert_xpath '//em[text()="askew"]', result, 1
 1475     end
 1476 
 1477     test 'compat mode in AsciiDoc table cell can be unset if set in parent document' do
 1478       input = <<~'EOS'
 1479       :compat-mode:
 1480 
 1481       The word 'italic' is emphasized.
 1482 
 1483       [cols=1*]
 1484       |===
 1485       |The word 'oblique' is emphasized.
 1486       a|
 1487       :!compat-mode:
 1488 
 1489       The word 'slanted' is not emphasized.
 1490       |===
 1491 
 1492       The word 'askew' is emphasized.
 1493       EOS
 1494 
 1495       result = convert_string_to_embedded input
 1496       assert_xpath '//em[text()="italic"]', result, 1
 1497       assert_xpath '//em[text()="oblique"]', result, 1
 1498       assert_xpath '//em[text()="slanted"]', result, 0
 1499       assert_xpath '//em[text()="askew"]', result, 1
 1500     end
 1501 
 1502     test 'nested table' do
 1503       input = <<~'EOS'
 1504       [cols="1,2a"]
 1505       |===
 1506       |Normal cell
 1507       |Cell with nested table
 1508       [cols="2,1"]
 1509       !===
 1510       !Nested table cell 1 !Nested table cell 2
 1511       !===
 1512       |===
 1513       EOS
 1514       output = convert_string_to_embedded input
 1515       assert_css 'table', output, 2
 1516       assert_css 'table table', output, 1
 1517       assert_css 'table > tbody > tr > td:nth-child(2) table', output, 1
 1518       assert_css 'table > tbody > tr > td:nth-child(2) table > tbody > tr > td', output, 2
 1519     end
 1520 
 1521     test 'can set format of nested table to psv' do
 1522       input = <<~'EOS'
 1523       [cols="2*"]
 1524       |===
 1525       |normal cell
 1526       a|
 1527       [format=psv]
 1528       !===
 1529       !nested cell
 1530       !===
 1531       |===
 1532       EOS
 1533 
 1534       output = convert_string_to_embedded input
 1535       assert_css 'table', output, 2
 1536       assert_css 'table table', output, 1
 1537       assert_css 'table > tbody > tr > td:nth-child(2) table', output, 1
 1538       assert_css 'table > tbody > tr > td:nth-child(2) table > tbody > tr > td', output, 1
 1539     end
 1540 
 1541     test 'toc from parent document should not be included in an AsciiDoc table cell' do
 1542       input = <<~'EOS'
 1543       = Document Title
 1544       :toc:
 1545 
 1546       == Section A
 1547 
 1548       |===
 1549       a|AsciiDoc content
 1550       |===
 1551       EOS
 1552 
 1553       output = convert_string input
 1554       assert_css '.toc', output, 1
 1555       assert_css 'table .toc', output, 0
 1556     end
 1557 
 1558     test 'should be able to enable toc in an AsciiDoc table cell' do
 1559       input = <<~'EOS'
 1560       = Document Title
 1561 
 1562       == Section A
 1563 
 1564       |===
 1565       a|
 1566       = Subdocument Title
 1567       :toc:
 1568 
 1569       == Subdocument Section A
 1570 
 1571       content
 1572       |===
 1573       EOS
 1574 
 1575       output = convert_string input
 1576       assert_css '.toc', output, 1
 1577       assert_css 'table .toc', output, 1
 1578     end
 1579 
 1580     test 'should be able to enable toc in both outer document and in an AsciiDoc table cell' do
 1581       input = <<~'EOS'
 1582       = Document Title
 1583       :toc:
 1584 
 1585       == Section A
 1586 
 1587       |===
 1588       a|
 1589       = Subdocument Title
 1590       :toc: macro
 1591 
 1592       [#table-cell-toc]
 1593       toc::[]
 1594 
 1595       == Subdocument Section A
 1596 
 1597       content
 1598       |===
 1599       EOS
 1600 
 1601       output = convert_string input
 1602       assert_css '.toc', output, 2
 1603       assert_css '#toc', output, 1
 1604       assert_css 'table .toc', output, 1
 1605       assert_css 'table #table-cell-toc', output, 1
 1606     end
 1607 
 1608     test 'document in an AsciiDoc table cell should not see doctitle of parent' do
 1609       input = <<~'EOS'
 1610       = Document Title
 1611 
 1612       [cols="1a"]
 1613       |===
 1614       |AsciiDoc content
 1615       |===
 1616       EOS
 1617 
 1618       output = convert_string input
 1619       assert_css 'table', output, 1
 1620       assert_css 'table > tbody > tr > td', output, 1
 1621       assert_css 'table > tbody > tr > td #preamble', output, 0
 1622       assert_css 'table > tbody > tr > td .paragraph', output, 1
 1623     end
 1624 
 1625     test 'cell background color' do
 1626       input = <<~'EOS'
 1627       [cols="1e,1", options="header"]
 1628       |===
 1629       |{set:cellbgcolor:green}green
 1630       |{set:cellbgcolor!}
 1631       plain
 1632       |{set:cellbgcolor:red}red
 1633       |{set:cellbgcolor!}
 1634       plain
 1635       |===
 1636       EOS
 1637 
 1638       output = convert_string_to_embedded input
 1639       assert_xpath '(/table/thead/tr/th)[1][@style="background-color: green;"]', output, 1
 1640       assert_xpath '(/table/thead/tr/th)[2][@style="background-color: green;"]', output, 0
 1641       assert_xpath '(/table/tbody/tr/td)[1][@style="background-color: red;"]', output, 1
 1642       assert_xpath '(/table/tbody/tr/td)[2][@style="background-color: green;"]', output, 0
 1643     end
 1644 
 1645     test 'should warn if table block is not terminated' do
 1646       input = <<~'EOS'
 1647       outside
 1648 
 1649       |===
 1650       |
 1651       inside
 1652 
 1653       still inside
 1654 
 1655       eof
 1656       EOS
 1657 
 1658       using_memory_logger do |logger|
 1659         output = convert_string_to_embedded input
 1660         assert_xpath '/table', output, 1
 1661         assert_message logger, :WARN, '<stdin>: line 3: unterminated table block', Hash
 1662       end
 1663     end
 1664 
 1665     test 'should show correct line number in warning about unterminated block inside AsciiDoc table cell' do
 1666       input = <<~'EOS'
 1667       outside
 1668 
 1669       * list item
 1670       +
 1671       |===
 1672       |cell
 1673       a|inside
 1674 
 1675       ====
 1676       unterminated example block
 1677       |===
 1678 
 1679       eof
 1680       EOS
 1681 
 1682       using_memory_logger do |logger|
 1683         output = convert_string_to_embedded input
 1684         assert_xpath '//ul//table', output, 1
 1685         assert_message logger, :WARN, '<stdin>: line 9: unterminated example block', Hash
 1686       end
 1687     end
 1688 
 1689     test 'custom separator for an AsciiDoc table cell' do
 1690       input = <<~'EOS'
 1691       [cols=2,separator=!]
 1692       |===
 1693       !Pipe output to vim
 1694       a!
 1695       ----
 1696       asciidoctor -o - -s test.adoc | view -
 1697       ----
 1698       |===
 1699       EOS
 1700       output = convert_string_to_embedded input
 1701       assert_css 'table', output, 1
 1702       assert_css 'table > colgroup > col', output, 2
 1703       assert_css 'table > tbody > tr', output, 1
 1704       assert_css 'table > tbody > tr:nth-child(1) > td', output, 2
 1705       assert_css 'table > tbody > tr:nth-child(1) > td:nth-child(1) p', output, 1
 1706       assert_css 'table > tbody > tr:nth-child(1) > td:nth-child(2) .listingblock', output, 1
 1707     end
 1708 
 1709     test 'table with breakable option docbook 5' do
 1710       input = <<~'EOS'
 1711       .Table with breakable
 1712       [%breakable]
 1713       |===
 1714       |Item       |Quantity
 1715       |Item 1     |1
 1716       |===
 1717       EOS
 1718       output = convert_string_to_embedded input, backend: 'docbook5'
 1719       assert_includes output, '<?dbfo keep-together="auto"?>'
 1720     end
 1721 
 1722     test 'table with unbreakable option docbook 5' do
 1723       input = <<~'EOS'
 1724       .Table with unbreakable
 1725       [%unbreakable]
 1726       |===
 1727       |Item       |Quantity
 1728       |Item 1     |1
 1729       |===
 1730       EOS
 1731       output = convert_string_to_embedded input, backend: 'docbook5'
 1732       assert_includes output, '<?dbfo keep-together="always"?>'
 1733     end
 1734 
 1735     test 'no implicit header row if cell in first line is quoted and spans multiple lines' do
 1736       input = <<~'EOS'
 1737       [cols=2*l]
 1738       ,===
 1739       "A1
 1740 
 1741       A1 continued",B1
 1742       A2,B2
 1743       ,===
 1744       EOS
 1745       output = convert_string_to_embedded input
 1746       assert_css 'table', output, 1
 1747       assert_css 'table > colgroup > col', output, 2
 1748       assert_css 'table > thead', output, 0
 1749       assert_css 'table > tbody', output, 1
 1750       assert_css 'table > tbody > tr', output, 2
 1751       assert_xpath %((//td)[1]//pre[text()="A1\n\nA1 continued"]), output, 1
 1752     end
 1753   end
 1754 
 1755   context 'DSV' do
 1756     test 'converts simple dsv table' do
 1757       input = <<~'EOS'
 1758       [width="75%",format="dsv"]
 1759       |===
 1760       root:x:0:0:root:/root:/bin/bash
 1761       bin:x:1:1:bin:/bin:/sbin/nologin
 1762       mysql:x:27:27:MySQL\:Server:/var/lib/mysql:/bin/bash
 1763       gdm:x:42:42::/var/lib/gdm:/sbin/nologin
 1764       sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
 1765       nobody:x:99:99:Nobody:/:/sbin/nologin
 1766       |===
 1767       EOS
 1768       doc = document_from_string input, standalone: false
 1769       table = doc.blocks[0]
 1770       assert 100, table.columns.map {|col| col.attributes['colpcwidth'] }.reduce(:+)
 1771       output = doc.convert
 1772       assert_css 'table', output, 1
 1773       assert_css 'table > colgroup > col[style*="width: 14.2857"]', output, 6
 1774       assert_css 'table > colgroup > col:last-of-type[style*="width: 14.2858%"]', output, 1
 1775       assert_css 'table > tbody > tr', output, 6
 1776       assert_xpath '//tr[4]/td[5]/p/text()', output, 0
 1777       assert_xpath '//tr[3]/td[5]/p[text()="MySQL:Server"]', output, 1
 1778     end
 1779 
 1780     test 'dsv format shorthand' do
 1781       input = <<~'EOS'
 1782       :===
 1783       a:b:c
 1784       1:2:3
 1785       :===
 1786       EOS
 1787       output = convert_string_to_embedded input
 1788       assert_css 'table', output, 1
 1789       assert_css 'table > colgroup > col', output, 3
 1790       assert_css 'table > tbody > tr', output, 2
 1791       assert_css 'table > tbody > tr:nth-child(1) > td', output, 3
 1792       assert_css 'table > tbody > tr:nth-child(2) > td', output, 3
 1793     end
 1794 
 1795     test 'single cell in DSV table should only produce single row' do
 1796       input = <<~'EOS'
 1797       :===
 1798       single cell
 1799       :===
 1800       EOS
 1801 
 1802       output = convert_string_to_embedded input
 1803       assert_css 'table td', output, 1
 1804     end
 1805 
 1806     test 'should treat trailing colon as an empty cell' do
 1807       input = <<~'EOS'
 1808       :===
 1809       A1:
 1810       B1:B2
 1811       C1:C2
 1812       :===
 1813       EOS
 1814       output = convert_string_to_embedded input
 1815       assert_css 'table', output, 1
 1816       assert_css 'table > colgroup > col', output, 2
 1817       assert_css 'table > tbody > tr', output, 3
 1818       assert_xpath '/table/tbody/tr[1]/td', output, 2
 1819       assert_xpath '/table/tbody/tr[1]/td[1]/p[text()="A1"]', output, 1
 1820       assert_xpath '/table/tbody/tr[1]/td[2]/p', output, 0
 1821       assert_xpath '/table/tbody/tr[2]/td[1]/p[text()="B1"]', output, 1
 1822     end
 1823   end
 1824 
 1825   context 'CSV' do
 1826     test 'should treat trailing comma as an empty cell' do
 1827       input = <<~'EOS'
 1828       ,===
 1829       A1,
 1830       B1,B2
 1831       C1,C2
 1832       ,===
 1833       EOS
 1834       output = convert_string_to_embedded input
 1835       assert_css 'table', output, 1
 1836       assert_css 'table > colgroup > col', output, 2
 1837       assert_css 'table > tbody > tr', output, 3
 1838       assert_xpath '/table/tbody/tr[1]/td', output, 2
 1839       assert_xpath '/table/tbody/tr[1]/td[1]/p[text()="A1"]', output, 1
 1840       assert_xpath '/table/tbody/tr[1]/td[2]/p', output, 0
 1841       assert_xpath '/table/tbody/tr[2]/td[1]/p[text()="B1"]', output, 1
 1842     end
 1843 
 1844     test 'should log error but not crash if cell data has unclosed quote' do
 1845       input = <<~'EOS'
 1846       ,===
 1847       a,b
 1848       c,"
 1849       ,===
 1850       EOS
 1851       using_memory_logger do |logger|
 1852         output = convert_string_to_embedded input
 1853         assert_css 'table', output, 1
 1854         assert_css 'table td', output, 4
 1855         assert_xpath '(/table/td)[4]/p', output, 0
 1856         assert_message logger, :ERROR, '<stdin>: line 3: unclosed quote in CSV data; setting cell to empty', Hash
 1857       end
 1858     end
 1859 
 1860     test 'should preserve newlines in quoted CSV values' do
 1861       input = <<~'EOS'
 1862       [cols="1,1,1l"]
 1863       ,===
 1864       "A
 1865       B
 1866       C","one
 1867 
 1868       two
 1869 
 1870       three","do
 1871 
 1872       re
 1873 
 1874       me"
 1875       ,===
 1876       EOS
 1877       output = convert_string_to_embedded input
 1878       assert_css 'table', output, 1
 1879       assert_css 'table > colgroup > col', output, 3
 1880       assert_css 'table > tbody > tr', output, 1
 1881       assert_xpath '/table/tbody/tr[1]/td', output, 3
 1882       assert_xpath %(/table/tbody/tr[1]/td[1]/p[text()="A\nB\nC"]), output, 1
 1883       assert_xpath '/table/tbody/tr[1]/td[2]/p', output, 3
 1884       assert_xpath '/table/tbody/tr[1]/td[2]/p[1][text()="one"]', output, 1
 1885       assert_xpath '/table/tbody/tr[1]/td[2]/p[2][text()="two"]', output, 1
 1886       assert_xpath '/table/tbody/tr[1]/td[2]/p[3][text()="three"]', output, 1
 1887       assert_xpath %(/table/tbody/tr[1]/td[3]//pre[text()="do\n\nre\n\nme"]), output, 1
 1888     end
 1889 
 1890     test 'mixed unquoted records and quoted records with escaped quotes, commas, and wrapped lines' do
 1891       input = <<~'EOS'
 1892       [format="csv",options="header"]
 1893       |===
 1894       Year,Make,Model,Description,Price
 1895       1997,Ford,E350,"ac, abs, moon",3000.00
 1896       1999,Chevy,"Venture ""Extended Edition""","",4900.00
 1897       1999,Chevy,"Venture ""Extended Edition, Very Large""",,5000.00
 1898       1996,Jeep,Grand Cherokee,"MUST SELL!
 1899       air, moon roof, loaded",4799.00
 1900       2000,Toyota,Tundra,"""This one's gonna to blow you're socks off,"" per the sticker",10000.00
 1901       2000,Toyota,Tundra,"Check it, ""this one's gonna to blow you're socks off"", per the sticker",10000.00
 1902       |===
 1903       EOS
 1904       output = convert_string_to_embedded input
 1905       assert_css 'table', output, 1
 1906       assert_css 'table > colgroup > col[style*="width: 20%"]', output, 5
 1907       assert_css 'table > thead > tr', output, 1
 1908       assert_css 'table > tbody > tr', output, 6
 1909       assert_xpath '((//tbody/tr)[1]/td)[4]/p[text()="ac, abs, moon"]', output, 1
 1910       assert_xpath %(((//tbody/tr)[2]/td)[3]/p[text()='Venture "Extended Edition"']), output, 1
 1911       assert_xpath %(((//tbody/tr)[4]/td)[4]/p[text()="MUST SELL!\nair, moon roof, loaded"]), output, 1
 1912       assert_xpath %(((//tbody/tr)[5]/td)[4]/p[text()='"This one#{decode_char 8217}s gonna to blow you#{decode_char 8217}re socks off," per the sticker']), output, 1
 1913       assert_xpath %(((//tbody/tr)[6]/td)[4]/p[text()='Check it, "this one#{decode_char 8217}s gonna to blow you#{decode_char 8217}re socks off", per the sticker']), output, 1
 1914     end
 1915 
 1916     test 'should allow quotes around a CSV value to be on their own lines' do
 1917       input = <<~'EOS'
 1918       [cols=2*]
 1919       ,===
 1920       "
 1921       A
 1922       ","
 1923       B
 1924       "
 1925       ,===
 1926       EOS
 1927       output = convert_string_to_embedded input
 1928       assert_css 'table', output, 1
 1929       assert_css 'table > colgroup > col', output, 2
 1930       assert_css 'table > tbody > tr', output, 1
 1931       assert_xpath '/table/tbody/tr[1]/td', output, 2
 1932       assert_xpath '/table/tbody/tr[1]/td[1]/p[text()="A"]', output, 1
 1933       assert_xpath '/table/tbody/tr[1]/td[2]/p[text()="B"]', output, 1
 1934     end
 1935 
 1936     test 'csv format shorthand' do
 1937       input = <<~'EOS'
 1938       ,===
 1939       a,b,c
 1940       1,2,3
 1941       ,===
 1942       EOS
 1943       output = convert_string_to_embedded input
 1944       assert_css 'table', output, 1
 1945       assert_css 'table > colgroup > col', output, 3
 1946       assert_css 'table > tbody > tr', output, 2
 1947       assert_css 'table > tbody > tr:nth-child(1) > td', output, 3
 1948       assert_css 'table > tbody > tr:nth-child(2) > td', output, 3
 1949     end
 1950 
 1951     test 'tsv as format' do
 1952       input = <<~EOS
 1953       [format=tsv]
 1954       ,===
 1955       a\tb\tc
 1956       1\t2\t3
 1957       ,===
 1958       EOS
 1959       output = convert_string_to_embedded input
 1960       assert_css 'table', output, 1
 1961       assert_css 'table > colgroup > col', output, 3
 1962       assert_css 'table > tbody > tr', output, 2
 1963       assert_css 'table > tbody > tr:nth-child(1) > td', output, 3
 1964       assert_css 'table > tbody > tr:nth-child(2) > td', output, 3
 1965     end
 1966 
 1967     test 'custom csv separator' do
 1968       input = <<~'EOS'
 1969       [format=csv,separator=;]
 1970       |===
 1971       a;b;c
 1972       1;2;3
 1973       |===
 1974       EOS
 1975       output = convert_string_to_embedded input
 1976       assert_css 'table', output, 1
 1977       assert_css 'table > colgroup > col', output, 3
 1978       assert_css 'table > tbody > tr', output, 2
 1979       assert_css 'table > tbody > tr:nth-child(1) > td', output, 3
 1980       assert_css 'table > tbody > tr:nth-child(2) > td', output, 3
 1981     end
 1982 
 1983     test 'tab as separator' do
 1984       input = <<~EOS
 1985       [separator=\\t]
 1986       ,===
 1987       a\tb\tc
 1988       1\t2\t3
 1989       ,===
 1990       EOS
 1991       output = convert_string_to_embedded input
 1992       assert_css 'table', output, 1
 1993       assert_css 'table > colgroup > col', output, 3
 1994       assert_css 'table > tbody > tr', output, 2
 1995       assert_css 'table > tbody > tr:nth-child(1) > td', output, 3
 1996       assert_css 'table > tbody > tr:nth-child(2) > td', output, 3
 1997     end
 1998 
 1999     test 'single cell in CSV table should only produce single row' do
 2000       input = <<~'EOS'
 2001       ,===
 2002       single cell
 2003       ,===
 2004       EOS
 2005 
 2006       output = convert_string_to_embedded input
 2007       assert_css 'table td', output, 1
 2008     end
 2009 
 2010     test 'cell formatted with AsciiDoc style' do
 2011       input = <<~'EOS'
 2012       [cols="1,1,1a",separator=;]
 2013       ,===
 2014       element;description;example
 2015 
 2016       thematic break,a visible break; also known as a horizontal rule;---
 2017       ,===
 2018       EOS
 2019 
 2020       output = convert_string_to_embedded input
 2021       assert_css 'table tbody hr', output, 1
 2022     end
 2023 
 2024     test 'should strip whitespace around contents of AsciiDoc cell' do
 2025       input = <<~'EOS'
 2026       [cols="1,1,1a",separator=;]
 2027       ,===
 2028       element;description;example
 2029 
 2030       paragraph;contiguous lines of words and phrases;"
 2031         one sentence, one line
 2032         "
 2033       ,===
 2034       EOS
 2035 
 2036       output = convert_string_to_embedded input
 2037       assert_xpath '/table/tbody//*[@class="paragraph"]/p[text()="one sentence, one line"]', output, 1
 2038     end
 2039   end
 2040 end