asciidoctor/asciidoctor-pdf

Image in table causes Prawn error

r0ckarong opened this issue · 9 comments

I have a document that uses an image stretched over multiple rows to describe UI options in one of our interfaces. In the HTML export this works fine. When I try to export this via asciidoctor-pdf I get the error:

Prawn::Errors::CannotFit
  Use --trace for backtrace

--trace yields a stack like this:

/Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/line_wrap.rb:243:in `update_output_based_on_last_fragment': Prawn::Errors::CannotFit (Prawn::Errors::CannotFit)
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/line_wrap.rb:226:in `fragment_finished'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/line_wrap.rb:113:in `block in add_fragment_to_line'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/line_wrap.rb:93:in `each'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/line_wrap.rb:93:in `add_fragment_to_line'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/line_wrap.rb:78:in `block in apply_font_settings_and_add_fragment_to_line'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/arranger.rb:255:in `block in apply_font_size'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/font.rb:101:in `font_size'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/prawn_ext/extensions.rb:249:in `font_size'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/arranger.rb:255:in `apply_font_size'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/arranger.rb:175:in `block in apply_font_settings'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/pdf-core-0.7.0/lib/pdf/core/text.rb:218:in `character_spacing'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/arranger.rb:166:in `apply_font_settings'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/line_wrap.rb:77:in `apply_font_settings_and_add_fragment_to_line'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/line_wrap.rb:47:in `wrap_line'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/wrap.rb:53:in `wrap'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/formatted_text/inline_image_arranger.rb:17:in `wrap'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/box.rb:226:in `block (4 levels) in render'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/font.rb:101:in `font_size'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/prawn_ext/extensions.rb:249:in `font_size'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/box.rb:219:in `block (3 levels) in render'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-templates-0.0.5/lib/prawn/text.rb:19:in `text_rendering_mode'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/box.rb:214:in `block (2 levels) in render'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/pdf-core-0.7.0/lib/pdf/core/text.rb:214:in `character_spacing'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/box.rb:213:in `block in render'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/font.rb:215:in `save_font'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/text/formatted/box.rb:212:in `render'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-table-0.2.2/lib/prawn/table/cell/text.rb:60:in `block in natural_content_height'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-table-0.2.2/lib/prawn/table/cell/text.rb:99:in `block in with_font'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-2.2.2/lib/prawn/font.rb:215:in `save_font'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-table-0.2.2/lib/prawn/table/cell/text.rb:92:in `with_font'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-table-0.2.2/lib/prawn/table/cell/text.rb:58:in `natural_content_height'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-table-0.2.2/lib/prawn/table/cell.rb:336:in `content_height'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-table-0.2.2/lib/prawn/table/cell.rb:309:in `height_ignoring_span'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-table-0.2.2/lib/prawn/table/cell.rb:325:in `height'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-table-0.2.2/lib/prawn/table.rb:373:in `block in row_heights'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-table-0.2.2/lib/prawn/table.rb:369:in `each'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-table-0.2.2/lib/prawn/table.rb:369:in `row_heights'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-table-0.2.2/lib/prawn/table.rb:656:in `set_row_heights'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-table-0.2.2/lib/prawn/table.rb:148:in `initialize'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-table-0.2.2/lib/prawn/table.rb:111:in `new'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/prawn-table-0.2.2/lib/prawn/table.rb:111:in `table'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/converter.rb:1727:in `convert_table'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/converter.rb:120:in `convert'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:71:in `convert'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:80:in `block in content'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:80:in `map'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:80:in `content'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/converter.rb:136:in `convert_content_for_block'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/converter.rb:426:in `convert_section'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/converter.rb:120:in `convert'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:71:in `convert'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:80:in `block in content'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:80:in `map'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:80:in `content'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/converter.rb:136:in `convert_content_for_block'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/converter.rb:426:in `convert_section'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/converter.rb:120:in `convert'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:71:in `convert'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:80:in `block in content'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:80:in `map'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:80:in `content'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/converter.rb:136:in `convert_content_for_block'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/converter.rb:426:in `convert_section'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/converter.rb:120:in `convert'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:71:in `convert'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:80:in `block in content'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:80:in `map'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/abstract_block.rb:80:in `content'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/document.rb:1110:in `content'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/converter.rb:136:in `convert_content_for_block'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/converter.rb:209:in `convert_document'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/lib/asciidoctor-pdf/converter.rb:120:in `convert'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/document.rb:1050:in `convert'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor.rb:1506:in `convert'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/cli/invoker.rb:95:in `block in invoke!'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/cli/invoker.rb:87:in `each'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-1.5.5/lib/asciidoctor/cli/invoker.rb:87:in `invoke!'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/gems/asciidoctor-pdf-1.5.0.alpha.15/bin/asciidoctor-pdf:31:in `<top (required)>'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/bin/asciidoctor-pdf:23:in `load'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/bin/asciidoctor-pdf:23:in `<main>'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/bin/ruby_executable_hooks:15:in `eval'
	from /Users/myuser/.rvm/gems/ruby-2.4.0/bin/ruby_executable_hooks:15:in `<main>'

The problem is the inline image in the table cell. Prawn then can't fit the table into the PDF.

The table is defined like this:

[options="header"]
|===
| |Number|Element|Function
.14+|image:search_options.jpg[search_options.jpg]

|1.|Type requested from HIRO Graph|List of available types to query for:  edges  vertices  gremlin
|2.|Preselection of vertex/edge types for results|Menu contents depend on graph data.
|3.|The actual search query|Request sent to the HIRO Graph API to look for elements with matching data. For examples see below.
|4.|Limit number of results|Sets the amount of results retrieved from the HIRO Graph API.
|5.|Attribute Fields|Determines which Attributes are retrieved from the HIRO Graph API.
|6.|Offset results by X entries|Ignores the first X results returned by the HIRO Graph API.
|7.|X Elements|Displays the number of results matching the search query.
|8.|By Field|Dropdown selection of the Attributes present in the results.
|9.|With Value|Dropdown selection of values for the Attributes present in the results.
|10.|Matching Elements|Displays the number of elements matching the selected filter criteria.
|11.|Number of Attributes|Lists the overall amount of different attributes present in the results.
|12.|Attribute Selection|Dropdown selection of all different Attributes in the results.
|13.|Values Count|Amount of different values present in the results.
|14.|Value distribution|Shows the distribution of identical values across the results.
|===

Image is attached.

search_options

screen shot 2017-07-04 at 15 06 01
screen shot 2017-07-04 at 15 06 07

I would expect to get at least a mention where this error occurs. I had to manually exclude all resources from my large export until I had found the offending page.

face-palm. Table cells in Asciidoctor PDF are my nemesis.

Technically, the converter has no access to source line numbers by default, so it's not possible to report the line. However, that does get me thinking...if the sourcemap is enabled, should the error messages include the line information that gets added to the nearest block? I think we can at least take that step. Let's pursue that in a separate issue.

I think this is related to #447. We were waiting on an upstream release, but that seems to have happened. I wonder if it got fixed or we are looking at something new.

I got this on Ubuntu 17.04 64 bits, asciidoc 8.6.9-5, asciidoctor 1.5.4, asciidoctor-pdf 1.5.0.alpha.16. Is there a newer release?

The problem here is the use of an image without an explicit width in a non-AsciiDoc table cell. If you write the table as follows, it will render properly:

[cols="2,1,3,3"]
|===
| |Number|Element|Function

.14+a|image::search-options.jpg[]

|1.|Type requested from HIRO Graph|List of available types to query for:  edges  vertices  gremlin
|2.|Preselection of vertex/edge types for results|Menu contents depend on graph data.
|3.|The actual search query|Request sent to the HIRO Graph API to look for elements with matching data. For examples see below.
|4.|Limit number of results|Sets the amount of results retrieved from the HIRO Graph API.
|5.|Attribute Fields|Determines which Attributes are retrieved from the HIRO Graph API.
|6.|Offset results by X entries|Ignores the first X results returned by the HIRO Graph API.
|7.|X Elements|Displays the number of results matching the search query.
|8.|By Field|Dropdown selection of the Attributes present in the results.
|9.|With Value|Dropdown selection of values for the Attributes present in the results.
|10.|Matching Elements|Displays the number of elements matching the selected filter criteria.
|11.|Number of Attributes|Lists the overall amount of different attributes present in the results.
|12.|Attribute Selection|Dropdown selection of all different Attributes in the results.
|13.|Values Count|Amount of different values present in the results.
|14.|Value distribution|Shows the distribution of identical values across the results.
|===

You can observe the same problem with this simple table:

|===
|image:search-options.jpg[] |Number |Element |Function
|===

If you give the image a (PDF) width that's less than the amount prawn-table allocates for the column, it will fit:

|===
|image:search-options.jpg[pdfwidth=1.5in] |Number |Element |Function
|===

Basically, prawn-table doesn't consider the width of the image when allocating the column widths. So you need to set the column width, then set the width of the image accordingly.

Using an AsciiDoc table cell also seems to solve the problem without having to assign a width to the image.

The following seems to work best:

|===
a|image::search-options.jpg[pdfwidth=100%] |Number |Element |Function
|===

(Note this doesn't work well with an autowidth table. In that case, set an absolute width value).

The best I can really do is document this scenario. The fact is that prawn-table will not try to increase the column width to accommodate the image (because it assumes the image is text that will wrap). So you have to adjust the widths (either the image, column, or both) until it fits.

i think should show where the error happens at least

i try to generate an existing adoc by source and get this error but don't where it happen, seem like I need to check all places of the image to find the table