asciidoctor / asciidoctor-pdf

:page_with_curl: Asciidoctor PDF: A native PDF converter for AsciiDoc based on Asciidoctor and Prawn, written entirely in Ruby.
https://docs.asciidoctor.org/pdf-converter/latest/
MIT License
1.14k stars 500 forks source link

Column spanning multiple (as in many) rows breaks the table layout #403

Closed GregorOphey closed 2 years ago

GregorOphey commented 8 years ago

Note: I really appreciate asciidoctor-pdf, since it does exactly what I need (in most cases) and allows to keep docs for html and pdf aligned easily. So thanks for all the good work!

However, for some documents I work with, the adoc is generated from xml sources, where there tend to be some border cases with excessively long lists of elements and such.

In this specific case I tried to work around the asciidoctor-pdf limitation #6 for putting lists into table cells, by putting the name of a group into a cell that spans multiple rows and add rows for each group member as follows

[grid="none"]
[cols="<3, <7"]
|=========================
 .10+|Group
 | member 1

 | member 2

 | member 3

 | member 4

 | member 5

 | member 6

 | member 7

 | member 8

 | member 9

 | member 10

|=========================

This produces very satisfying PDF output in general:

tableList10.pdf

However when the Group starts to exceed more than one page, the members colunm (incl. the border) is shown on the last page only.

Here is a cell spanning 100 rows to illustrate the general behavior:

tableList100.pdf

With the the customized theme I am using where

page:
  layout: portrait
  margin: [0.9in, 0.7in, 1.3in, 0.7in]
  size: A4
base:
  align: justify
  font_family: Helvetica
  font_size: 10.0
  line_height_length: 12
  line_height: $base_line_height_length / $base_font_size

I assume might affect available lines per page, the border line is between 33 and 34 rows:

tableList34.pdf tableList33.pdf

Page breaks seem to be problematic in general for this, since also a 10 row table spanning a page break causes this behavior:

tableList10time4.pdf

You can use the following code (as I did) to generate your own test files (number of rows is first parameter ...)

pre = <<END
[grid="none"]
[cols="<3, <7"]
|=========================
END

File.open("tableList#{ARGV.first}.adoc", "w") do |adocFile|
  adocFile.puts pre ;
  adocFile.puts " .#{ARGV.first}+|Group"
  (1..ARGV.first.to_i).each { |i| adocFile.puts " | member #{i}\n\n"; };
  adocFile.puts '|=========================';
end

Let me know, if you need anything else. I'd be happy to help by analyzing this further ... just point me in the right direction ...

mojavelinux commented 8 years ago

This appears to be caused by issue https://github.com/prawnpdf/prawn-table/issues/70 in prawn-table. For tables, all Asciidoctor PDF does is construct an array of table data and settings and pass those to prawn-table to handle the drawing. If prawn-table gets it wrong, then Asciidoctor PDF gets it wrong. I'm going to mark this as upstream. I encourage you to try to duplicate your use case using the prawn-table API to help the developers understand, solve, and test the problem.

lostDev0 commented 7 years ago

Any time the cell height exceeds the page height this happens.

|===
5+| foobar | foobar | foobar
.20+| foobar
.10+| foobar
3+| foobar | foobar | foobar
3+| foobar | foobar  | foobar
3+| foobar | foobar | foobar
.7+| foobar
2+| foobar | foobar foobar foobar  foobar foobar  foobar | foobar
2+| foobar | foobar foobar foobar  foobar foobar  foobar | foobar
2+| foobar | foobar foobar foobar  foobar foobar  foobar | foobar
2+| foobar | foobar foobar foobar  foobar foobar  foobar | foobar
2+| foobar | foobar foobar foobar  foobar foobar  foobar | foobar
.2+| foobar
| foobar | foobar | foobar
| foobar | foobar | foobar
.10+| foobar
3+| foobar | foobar foobar foobar  foobar foobar  foobar| foobar
3+| foobar | foobar foobar foobar  foobar foobar  foobar | foobar
3+| foobar | foobar foobar foobar  foobar foobar  foobar | foobar
.7+| foobar
2+| foobar | foobar foobar foobar  foobar foobar  foobar |  foobar
2+| foobar | foobar foobar foobar  foobar foobar  foobar  | foobar
2+| foobar | foobar foobar foobar  foobar foobar  foobar | foobar
2+| foobar | foobar foobar foobar  foobar foobar  foobar | foobar
2+| foobar | foobar | foobar
.2+| foobar
| foobar | foobar | foobar
| foobar | foobar | foobar
|===
mojavelinux commented 2 years ago

Any time the cell height exceeds the page height this happens.

That's a different issue. When using this converter (due to a limitation in prawn-table), a cell cannot exceed the height of the page. This is mentioned in the list of limitations. See https://docs.asciidoctor.org/pdf-converter/latest/features/#limitations

mojavelinux commented 2 years ago

I've assessed the problem reported by this issue and I'm afraid there's nothing we can do. It's a hard limitation of prawn-table that a rowspan cell cannot exceed the height of a page. You can reproduce the problem without Asciidoctor PDF by running this script:

require 'prawn'
require 'prawn/table'

Prawn::Document.generate 'out.pdf' do
  table_data = [[{ colspan: 1, rowspan: 35, content: 'Group' }, { colspan: 1, rowspan: 1, content: 'Member 1' }]]
  34.times do |idx|
    table_data << [{ colspan: 1, rowspan: 1, content: %(Member #{idx + 2}) }]
  end
  table table_data, width: bounds.width
end

This is similar to https://github.com/prawnpdf/prawn-table/issues/133, though the problem has been reported many other times.

I just don't have time right now to dry to dissect the code in prawn-table to figure out how we could lift this limitation. The best advice I can offer is to split up the cells so that they don't exceed this limit.

I suppose prawn-table would need to detect the situation where a rowspan is forcing a cell to become taller than the height of the page and automatically split that rowspan so that part can go on one page and part goes on the next. If someone knows how to fix it, please chime in and we can revisit. See https://github.com/prawnpdf/prawn-table/blob/master/lib/prawn/table.rb#L265

As a stop-gap, I'm willing to apply the fix proposed in https://github.com/prawnpdf/prawn-table/issues/106. That seems reasonable to me as at least it would allow rowspans that do fit on a page to work. I think that's a reasonable compromise to start with.