summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/asciidoctor/parser.rb12
-rw-r--r--lib/asciidoctor/table.rb61
-rw-r--r--test/tables_test.rb24
3 files changed, 62 insertions, 35 deletions
diff --git a/lib/asciidoctor/parser.rb b/lib/asciidoctor/parser.rb
index e7755fb1..1dae26fa 100644
--- a/lib/asciidoctor/parser.rb
+++ b/lib/asciidoctor/parser.rb
@@ -2272,10 +2272,10 @@ class Parser
table.assign_caption attributes.delete('caption')
end
- if attributes['cols'].nil_or_empty?
+ if (cols = attributes['cols']).nil_or_empty? || (cols = cols.rstrip).empty?
explicit_col_specs = false
else
- table.create_columns(parse_col_specs(attributes['cols']))
+ table.create_columns(parse_col_specs cols)
explicit_col_specs = true
end
@@ -2372,12 +2372,8 @@ class Parser
end
end
- table.attributes['colcount'] ||= parser_ctx.col_count
-
- if !explicit_col_specs
- # TODO further encapsulate this logic (into table perhaps?)
- even_width = (100.0 / parser_ctx.col_count).floor
- table.columns.each {|c| c.assign_width(0, even_width) }
+ unless (table.attributes['colcount'] ||= table.columns.size) == 0 || explicit_col_specs
+ table.assign_col_widths
end
table.partition_header_footer attributes
diff --git a/lib/asciidoctor/table.rb b/lib/asciidoctor/table.rb
index bd900ede..95873887 100644
--- a/lib/asciidoctor/table.rb
+++ b/lib/asciidoctor/table.rb
@@ -99,21 +99,45 @@ class Table < AbstractBlock
# Internal: Creates the Column objects from the column spec
#
# returns nothing
- def create_columns(col_specs)
- total_width = 0
+ def create_columns col_specs
cols = []
+ width_base = 0
col_specs.each do |col_spec|
- total_width += col_spec['width']
- cols << Column.new(self, cols.size, col_spec)
+ width_base += col_spec['width']
+ cols << (Column.new self, cols.size, col_spec)
end
-
- unless cols.empty?
+ unless (@columns = cols).empty?
@attributes['colcount'] = cols.size
- even_width = (100.0 / cols.size).floor
- cols.each {|c| c.assign_width(total_width, even_width) }
+ assign_col_widths(width_base == 0 ? nil : width_base)
end
+ nil
+ end
+
+ # Internal: Assign column widths to columns
+ #
+ # This method rounds the percentage width values to 4 decimal places and
+ # donates the balance to the final column.
+ #
+ # This method assumes there's at least one column in the columns array.
+ #
+ # width_base - the total of the relative column values used for calculating percentage widths (default: nil)
+ #
+ # returns nothing
+ def assign_col_widths width_base = nil
+ pf = 10.0 ** 4 # precision factor (multipler / divisor) for managing precision of calculated result
+ total_width = col_pcwidth = 0
+
+ if width_base
+ @columns.each {|col| total_width += (col_pcwidth = col.assign_width nil, width_base, pf) }
+ else
+ col_pcwidth = ((100 * pf / @columns.size).to_i) / pf
+ col_pcwidth = col_pcwidth.to_i if col_pcwidth.to_i == col_pcwidth
+ @columns.each {|col| total_width += col.assign_width col_pcwidth }
+ end
+
+ # donate balance, if any, to final column
+ @columns[-1].assign_width(((100 - total_width + col_pcwidth) * pf).round / pf) unless total_width == 100
- @columns = cols
nil
end
@@ -167,19 +191,18 @@ class Table::Column < AbstractNode
#
# This method assigns the colpcwidth and colabswidth attributes.
#
- # returns nothing
- def assign_width(total_width, even_width)
- if total_width > 0
- width = ((@attributes['width'].to_f / total_width) * 100).floor
- else
- width = even_width
+ # returns the resolved colpcwidth value
+ def assign_width col_pcwidth, width_base = nil, pf = 10000.0
+ if width_base
+ col_pcwidth = ((@attributes['width'].to_f / width_base) * 100 * pf).to_i / pf
+ col_pcwidth = col_pcwidth.to_i if col_pcwidth.to_i == col_pcwidth
end
- @attributes['colpcwidth'] = width
+ @attributes['colpcwidth'] = col_pcwidth
if parent.attributes.key? 'tableabswidth'
- @attributes['colabswidth'] = ((width.to_f / 100) * parent.attributes['tableabswidth']).round
+ # FIXME calculate more accurately (only used in DocBook output)
+ @attributes['colabswidth'] = ((col_pcwidth / 100.0) * parent.attributes['tableabswidth']).round
end
-
- nil
+ col_pcwidth
end
end
diff --git a/test/tables_test.rb b/test/tables_test.rb
index 15b9c3c3..09905935 100644
--- a/test/tables_test.rb
+++ b/test/tables_test.rb
@@ -16,10 +16,14 @@ context 'Tables' do
|=======
EOS
cells = [%w(A B C), %w(a b c), %w(1 2 3)]
- output = render_embedded_string input
+ doc = document_from_string input, :header_footer => false
+ table = doc.blocks[0]
+ assert 100, table.columns.map {|col| col.attributes['colpcwidth'] }.reduce(:+)
+ output = doc.convert
assert_css 'table', output, 1
assert_css 'table.tableblock.frame-all.grid-all.spread', output, 1
- assert_css 'table > colgroup > col[style*="width: 33%"]', output, 3
+ assert_css 'table > colgroup > col[style*="width: 33.3333%"]', output, 2
+ assert_css 'table > colgroup > col:last-of-type[style*="width: 33.3334%"]', output, 1
assert_css 'table tr', output, 3
assert_css 'table > tbody > tr', output, 3
assert_css 'table td', output, 9
@@ -489,10 +493,10 @@ I am getting in shape!
assert_css 'table[style*="width: 80%"]', output, 1
assert_xpath '/table/caption[@class="title"][text()="Table 1. Horizontal and vertical source data"]', output, 1
assert_css 'table > colgroup > col', output, 4
- assert_css 'table > colgroup > col:nth-child(1)[@style*="width: 17%"]', output, 1
- assert_css 'table > colgroup > col:nth-child(2)[@style*="width: 11%"]', output, 1
- assert_css 'table > colgroup > col:nth-child(3)[@style*="width: 11%"]', output, 1
- assert_css 'table > colgroup > col:nth-child(4)[@style*="width: 58%"]', output, 1
+ assert_css 'table > colgroup > col:nth-child(1)[@style*="width: 17.647%"]', output, 1
+ assert_css 'table > colgroup > col:nth-child(2)[@style*="width: 11.7647%"]', output, 1
+ assert_css 'table > colgroup > col:nth-child(3)[@style*="width: 11.7647%"]', output, 1
+ assert_css 'table > colgroup > col:nth-child(4)[@style*="width: 58.8236%"]', output, 1
assert_css 'table > thead', output, 1
assert_css 'table > thead > tr', output, 1
assert_css 'table > thead > tr > th', output, 4
@@ -1023,9 +1027,13 @@ sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
|===
EOS
- output = render_embedded_string input
+ doc = document_from_string input, :header_footer => false
+ table = doc.blocks[0]
+ assert 100, table.columns.map {|col| col.attributes['colpcwidth'] }.reduce(:+)
+ output = doc.convert
assert_css 'table', output, 1
- assert_css 'table > colgroup > col[style*="width: 14%"]', output, 7
+ assert_css 'table > colgroup > col[style*="width: 14.2857"]', output, 6
+ assert_css 'table > colgroup > col:last-of-type[style*="width: 14.2858%"]', output, 1
assert_css 'table > tbody > tr', output, 6
assert_xpath '//tr[4]/td[5]/p/text()', output, 0
assert_xpath '//tr[3]/td[5]/p[text()="MySQL:Server"]', output, 1