asciidoctor 1.5.3 → 1.5.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of asciidoctor might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +67 -5
- data/CONTRIBUTING.adoc +171 -0
- data/LICENSE.adoc +1 -1
- data/README.adoc +62 -30
- data/bin/asciidoctor +3 -3
- data/bin/asciidoctor-safe +8 -5
- data/lib/asciidoctor.rb +10 -21
- data/lib/asciidoctor/abstract_block.rb +29 -11
- data/lib/asciidoctor/abstract_node.rb +11 -6
- data/lib/asciidoctor/callouts.rb +6 -10
- data/lib/asciidoctor/cli/options.rb +2 -2
- data/lib/asciidoctor/converter.rb +1 -1
- data/lib/asciidoctor/converter/docbook5.rb +46 -23
- data/lib/asciidoctor/converter/factory.rb +3 -3
- data/lib/asciidoctor/converter/html5.rb +27 -24
- data/lib/asciidoctor/converter/manpage.rb +72 -61
- data/lib/asciidoctor/converter/template.rb +5 -9
- data/lib/asciidoctor/document.rb +18 -18
- data/lib/asciidoctor/extensions.rb +5 -5
- data/lib/asciidoctor/helpers.rb +2 -2
- data/lib/asciidoctor/inline.rb +2 -2
- data/lib/asciidoctor/parser.rb +59 -59
- data/lib/asciidoctor/path_resolver.rb +23 -15
- data/lib/asciidoctor/reader.rb +34 -29
- data/lib/asciidoctor/section.rb +6 -8
- data/lib/asciidoctor/substitutors.rb +2 -2
- data/lib/asciidoctor/table.rb +46 -23
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +11 -11
- data/man/asciidoctor.adoc +2 -2
- data/test/attributes_test.rb +21 -37
- data/test/blocks_test.rb +41 -14
- data/test/converter_test.rb +4 -4
- data/test/document_test.rb +61 -8
- data/test/extensions_test.rb +2 -2
- data/test/invoker_test.rb +3 -3
- data/test/links_test.rb +13 -3
- data/test/lists_test.rb +114 -114
- data/test/manpage_test.rb +203 -0
- data/test/paragraphs_test.rb +3 -3
- data/test/parser_test.rb +4 -4
- data/test/preamble_test.rb +1 -1
- data/test/reader_test.rb +149 -109
- data/test/sections_test.rb +137 -27
- data/test/substitutions_test.rb +24 -16
- data/test/tables_test.rb +183 -31
- data/test/test_helper.rb +10 -22
- metadata +9 -6
- data/compat/asciidoc.conf +0 -395
- data/compat/font-awesome-3-compat.css +0 -397
@@ -96,7 +96,7 @@ module Asciidoctor
|
|
96
96
|
# begin
|
97
97
|
# resolver.system_path('images', '/etc', '/path/to/docs')
|
98
98
|
# rescue SecurityError => e
|
99
|
-
# puts e.message
|
99
|
+
# puts e.message
|
100
100
|
# end
|
101
101
|
# => Start path /etc is outside of jail: /path/to/docs'
|
102
102
|
#
|
@@ -145,6 +145,9 @@ class PathResolver
|
|
145
145
|
# Windows roots can begin with drive letter
|
146
146
|
elsif @file_separator == BACKSLASH && WindowsRootRx =~ path
|
147
147
|
true
|
148
|
+
# Absolute paths in the browser start with file:///
|
149
|
+
elsif ::RUBY_ENGINE_OPAL && ::JAVASCRIPT_PLATFORM == 'browser' && (path.start_with? 'file:///')
|
150
|
+
true
|
148
151
|
else
|
149
152
|
false
|
150
153
|
end
|
@@ -167,7 +170,7 @@ class PathResolver
|
|
167
170
|
def is_web_root? path
|
168
171
|
path.start_with? SLASH
|
169
172
|
end
|
170
|
-
|
173
|
+
|
171
174
|
# Public: Normalize path by converting any backslashes to forward slashes
|
172
175
|
#
|
173
176
|
# path - the String path to normalize
|
@@ -198,7 +201,7 @@ class PathResolver
|
|
198
201
|
path_segments, path_root, _ = partition_path path
|
199
202
|
join_path path_segments, path_root
|
200
203
|
end
|
201
|
-
|
204
|
+
|
202
205
|
# Public: Partition the path into path segments and remove any empty segments
|
203
206
|
# or segments that are self references (.). The path is converted to a posix
|
204
207
|
# path before being partitioned.
|
@@ -211,7 +214,7 @@ class PathResolver
|
|
211
214
|
# path root (e.g., '/', './', 'c:/') if the path is absolute and the posix
|
212
215
|
# version of the path.
|
213
216
|
#--
|
214
|
-
# QUESTION is it worth it to normalize slashes? it doubles the time elapsed
|
217
|
+
# QUESTION is it worth it to normalize slashes? it doubles the time elapsed
|
215
218
|
def partition_path path, web_path = false
|
216
219
|
if (result = web_path ? @_partition_path_web[path] : @_partition_path_sys[path])
|
217
220
|
return result
|
@@ -238,7 +241,7 @@ class PathResolver
|
|
238
241
|
# ex. /sample/path
|
239
242
|
elsif posix_path.start_with? SLASH
|
240
243
|
SLASH
|
241
|
-
# ex. c:/sample/path
|
244
|
+
# ex. c:/sample/path (or file:///sample/path in browser environment)
|
242
245
|
else
|
243
246
|
posix_path[0..(posix_path.index SLASH)]
|
244
247
|
end
|
@@ -255,6 +258,11 @@ class PathResolver
|
|
255
258
|
# shift twice for a UNC path
|
256
259
|
if root == DOUBLE_SLASH
|
257
260
|
path_segments = path_segments[2..-1]
|
261
|
+
# shift twice for a file:/// path and adjust root
|
262
|
+
# NOTE technically file:/// paths work without this adjustment
|
263
|
+
#elsif ::RUBY_ENGINE_OPAL && ::JAVASCRIPT_PLATFORM == 'browser' && root == 'file:/'
|
264
|
+
# root = 'file://'
|
265
|
+
# path_segments = path_segments[2..-1]
|
258
266
|
# shift once for any other root
|
259
267
|
elsif root
|
260
268
|
path_segments.shift
|
@@ -265,7 +273,7 @@ class PathResolver
|
|
265
273
|
#posix_path = posix_path.chomp '/'
|
266
274
|
(web_path ? @_partition_path_web : @_partition_path_sys)[path] = [path_segments, root, posix_path]
|
267
275
|
end
|
268
|
-
|
276
|
+
|
269
277
|
# Public: Join the segments using the posix file separator (since Ruby knows
|
270
278
|
# how to work with paths specified this way, regardless of OS). Use the root,
|
271
279
|
# if specified, to construct an absolute path. Otherwise join the segments as
|
@@ -283,7 +291,7 @@ class PathResolver
|
|
283
291
|
segments * SLASH
|
284
292
|
end
|
285
293
|
end
|
286
|
-
|
294
|
+
|
287
295
|
# Public: Resolve a system path from the target and start paths. If a jail
|
288
296
|
# path is specified, enforce that the resolved directory is contained within
|
289
297
|
# the jail path. If a jail path is not provided, the resolved path may be
|
@@ -313,7 +321,7 @@ class PathResolver
|
|
313
321
|
if target.nil_or_empty?
|
314
322
|
target_segments = []
|
315
323
|
else
|
316
|
-
target_segments, target_root, _ = partition_path target
|
324
|
+
target_segments, target_root, _ = partition_path target
|
317
325
|
end
|
318
326
|
|
319
327
|
if target_segments.empty?
|
@@ -327,7 +335,7 @@ class PathResolver
|
|
327
335
|
return system_path start, jail, jail, opts
|
328
336
|
end
|
329
337
|
end
|
330
|
-
|
338
|
+
|
331
339
|
if target_root && target_root != DOT_SLASH
|
332
340
|
resolved_target = join_path target_segments, target_root
|
333
341
|
# if target is absolute and a sub-directory of jail, or
|
@@ -336,7 +344,7 @@ class PathResolver
|
|
336
344
|
return resolved_target
|
337
345
|
end
|
338
346
|
end
|
339
|
-
|
347
|
+
|
340
348
|
if start.nil_or_empty?
|
341
349
|
start = jail ? jail : @working_dir
|
342
350
|
elsif is_root? start
|
@@ -344,7 +352,7 @@ class PathResolver
|
|
344
352
|
else
|
345
353
|
start = system_path start, jail, jail, opts
|
346
354
|
end
|
347
|
-
|
355
|
+
|
348
356
|
# both jail and start have been posixfied at this point
|
349
357
|
if jail == start
|
350
358
|
jail_segments, jail_root, _ = partition_path jail
|
@@ -354,9 +362,9 @@ class PathResolver
|
|
354
362
|
raise ::SecurityError, %(#{opts[:target_name] || 'Start path'} #{start} is outside of jail: #{jail} (disallowed in safe mode))
|
355
363
|
end
|
356
364
|
|
357
|
-
start_segments, start_root, _ = partition_path start
|
365
|
+
start_segments, start_root, _ = partition_path start
|
358
366
|
jail_segments, jail_root, _ = partition_path jail
|
359
|
-
|
367
|
+
|
360
368
|
# Already checked for this condition
|
361
369
|
#if start_root != jail_root
|
362
370
|
# raise ::SecurityError, %(Jail root #{jail_root} does not match root of #{opts[:target_name] || 'start path'}: #{start_root})
|
@@ -365,7 +373,7 @@ class PathResolver
|
|
365
373
|
start_segments, start_root, _ = partition_path start
|
366
374
|
jail_root = start_root
|
367
375
|
end
|
368
|
-
|
376
|
+
|
369
377
|
resolved_segments = start_segments.dup
|
370
378
|
warned = false
|
371
379
|
target_segments.each do |segment|
|
@@ -386,7 +394,7 @@ class PathResolver
|
|
386
394
|
resolved_segments.push segment
|
387
395
|
end
|
388
396
|
end
|
389
|
-
|
397
|
+
|
390
398
|
join_path resolved_segments, jail_root
|
391
399
|
end
|
392
400
|
|
data/lib/asciidoctor/reader.rb
CHANGED
@@ -7,7 +7,7 @@ class Reader
|
|
7
7
|
attr_accessor :dir
|
8
8
|
attr_accessor :path
|
9
9
|
attr_accessor :lineno
|
10
|
-
|
10
|
+
|
11
11
|
def initialize file, dir = nil, path = nil, lineno = nil
|
12
12
|
@file = file
|
13
13
|
@dir = dir
|
@@ -147,7 +147,7 @@ class Reader
|
|
147
147
|
# returns the first element of the internal @lines Array. (default: false)
|
148
148
|
#
|
149
149
|
# Returns the next line of the source data as a String if there are lines remaining.
|
150
|
-
# Returns
|
150
|
+
# Returns nothing if there is no more data.
|
151
151
|
def peek_line direct = false
|
152
152
|
if direct || @look_ahead > 0
|
153
153
|
@unescape_next_line ? @lines[0][1..-1] : @lines[0]
|
@@ -205,7 +205,7 @@ class Reader
|
|
205
205
|
# returns the first element of the internal @lines Array. (default: false)
|
206
206
|
#
|
207
207
|
# Returns the String of the next line of the source data if data is present.
|
208
|
-
# Returns
|
208
|
+
# Returns nothing if there is no more data.
|
209
209
|
def read_line direct = false
|
210
210
|
if direct || @look_ahead > 0 || has_more_lines?
|
211
211
|
shift
|
@@ -245,7 +245,7 @@ class Reader
|
|
245
245
|
# direct - A Boolean flag to bypasses the check for more lines and immediately
|
246
246
|
# returns the first element of the internal @lines Array. (default: true)
|
247
247
|
#
|
248
|
-
#
|
248
|
+
# Returns a Boolean indicating whether there was a line to discard.
|
249
249
|
def advance direct = true
|
250
250
|
!!read_line(direct)
|
251
251
|
end
|
@@ -255,7 +255,9 @@ class Reader
|
|
255
255
|
# Since this line was (assumed to be) previously retrieved through the
|
256
256
|
# reader, it is marked as seen.
|
257
257
|
#
|
258
|
-
#
|
258
|
+
# line_to_restore - the line to restore onto the stack
|
259
|
+
#
|
260
|
+
# Returns nothing.
|
259
261
|
def unshift_line line_to_restore
|
260
262
|
unshift line_to_restore
|
261
263
|
nil
|
@@ -267,7 +269,7 @@ class Reader
|
|
267
269
|
# Since these lines were (assumed to be) previously retrieved through the
|
268
270
|
# reader, they are marked as seen.
|
269
271
|
#
|
270
|
-
# Returns
|
272
|
+
# Returns nothing.
|
271
273
|
def unshift_lines lines_to_restore
|
272
274
|
# QUESTION is it faster to use unshift(*lines_to_restore)?
|
273
275
|
lines_to_restore.reverse_each {|line| unshift line }
|
@@ -275,20 +277,22 @@ class Reader
|
|
275
277
|
end
|
276
278
|
alias :restore_lines :unshift_lines
|
277
279
|
|
278
|
-
# Public: Replace the
|
280
|
+
# Public: Replace the next line with the specified line.
|
279
281
|
#
|
280
282
|
# Calls Reader#advance to consume the current line, then calls
|
281
283
|
# Reader#unshift to push the replacement onto the top of the
|
282
284
|
# line stack.
|
283
285
|
#
|
284
|
-
# replacement
|
286
|
+
# replacement - The String line to put in place of the next line (i.e., the line at the cursor).
|
285
287
|
#
|
286
288
|
# Returns nothing.
|
287
|
-
def
|
289
|
+
def replace_next_line replacement
|
288
290
|
advance
|
289
291
|
unshift replacement
|
290
292
|
nil
|
291
293
|
end
|
294
|
+
# deprecated
|
295
|
+
alias :replace_line :replace_next_line
|
292
296
|
|
293
297
|
# Public: Strip off leading blank lines in the Array of lines.
|
294
298
|
#
|
@@ -441,7 +445,7 @@ class Reader
|
|
441
445
|
skip_comments = options[:skip_line_comments]
|
442
446
|
line_read = false
|
443
447
|
line_restored = false
|
444
|
-
|
448
|
+
|
445
449
|
complete = false
|
446
450
|
while !complete && (line = read_line)
|
447
451
|
complete = while true
|
@@ -462,7 +466,7 @@ class Reader
|
|
462
466
|
line_read = true
|
463
467
|
end
|
464
468
|
if options[:preserve_last_line]
|
465
|
-
|
469
|
+
unshift line
|
466
470
|
line_restored = true
|
467
471
|
end
|
468
472
|
else
|
@@ -656,7 +660,7 @@ class PreprocessorReader < Reader
|
|
656
660
|
#
|
657
661
|
# Returns the next line of the source data as a String if there are lines remaining
|
658
662
|
# in the current include context or a parent include context.
|
659
|
-
# Returns
|
663
|
+
# Returns nothing if there are no more lines remaining and the include stack is empty.
|
660
664
|
def peek_line direct = false
|
661
665
|
if (line = super)
|
662
666
|
line
|
@@ -687,7 +691,7 @@ class PreprocessorReader < Reader
|
|
687
691
|
# Used for a single-line conditional block in the case of the ifdef or
|
688
692
|
# ifndef directives, and for the conditional expression for the ifeval directive.
|
689
693
|
#
|
690
|
-
#
|
694
|
+
# Returns a Boolean indicating whether the cursor should be advanced
|
691
695
|
def preprocess_conditional_inclusion directive, target, delimiter, text
|
692
696
|
# must have a target before brackets if ifdef or ifndef
|
693
697
|
# must not have text between brackets if endif
|
@@ -773,8 +777,9 @@ class PreprocessorReader < Reader
|
|
773
777
|
unless @skipping || skip
|
774
778
|
# FIXME slight hack to skip past conditional line
|
775
779
|
# but keep our synthetic line marked as processed
|
780
|
+
# QUESTION can we use read_line true and unshift twice instead?
|
776
781
|
conditional_line = peek_line true
|
777
|
-
|
782
|
+
replace_next_line text.rstrip
|
778
783
|
unshift conditional_line
|
779
784
|
return true
|
780
785
|
end
|
@@ -803,16 +808,14 @@ class PreprocessorReader < Reader
|
|
803
808
|
# target - The name of the source document to include as specified in the
|
804
809
|
# target slot of the include::[] macro
|
805
810
|
#
|
806
|
-
#
|
811
|
+
# Returns a Boolean indicating whether the line under the cursor has changed.
|
807
812
|
def preprocess_include raw_target, raw_attributes
|
808
813
|
if (target = @document.sub_attributes raw_target, :attribute_missing => 'drop-line').empty?
|
814
|
+
advance
|
809
815
|
if @document.attributes.fetch('attribute-missing', Compliance.attribute_missing) == 'skip'
|
810
|
-
|
811
|
-
true
|
812
|
-
else
|
813
|
-
advance
|
814
|
-
true
|
816
|
+
unshift %(Unresolved directive in #{@path} - include::#{raw_target}[#{raw_attributes}])
|
815
817
|
end
|
818
|
+
true
|
816
819
|
# assume that if an include processor is given, the developer wants
|
817
820
|
# to handle when and how to process the include
|
818
821
|
elsif include_processors? &&
|
@@ -825,7 +828,7 @@ class PreprocessorReader < Reader
|
|
825
828
|
# however, be friendly and at least make it a link to the source document
|
826
829
|
elsif @document.safe >= SafeMode::SECURE
|
827
830
|
# FIXME we don't want to use a link macro if we are in a verbatim context
|
828
|
-
|
831
|
+
replace_next_line %(link:#{target}[])
|
829
832
|
true
|
830
833
|
elsif (abs_maxdepth = @maxdepth[:abs]) > 0 && @include_stack.size >= abs_maxdepth
|
831
834
|
warn %(asciidoctor: ERROR: #{line_info}: maximum include depth of #{@maxdepth[:rel]} exceeded)
|
@@ -843,7 +846,7 @@ class PreprocessorReader < Reader
|
|
843
846
|
end
|
844
847
|
elsif Helpers.uriish? target
|
845
848
|
unless @document.attributes.has_key? 'allow-uri-read'
|
846
|
-
|
849
|
+
replace_next_line %(link:#{target}[])
|
847
850
|
return true
|
848
851
|
end
|
849
852
|
|
@@ -863,7 +866,7 @@ class PreprocessorReader < Reader
|
|
863
866
|
include_file = @document.normalize_system_path(target, @dir, nil, :target_name => 'include file')
|
864
867
|
unless ::File.file? include_file
|
865
868
|
warn %(asciidoctor: WARNING: #{line_info}: include file not found: #{include_file})
|
866
|
-
|
869
|
+
replace_next_line %(Unresolved directive in #{@path} - include::#{target}[#{raw_attributes}])
|
867
870
|
return true
|
868
871
|
end
|
869
872
|
#path = @document.relative_path include_file
|
@@ -923,7 +926,7 @@ class PreprocessorReader < Reader
|
|
923
926
|
end
|
924
927
|
rescue
|
925
928
|
warn %(asciidoctor: WARNING: #{line_info}: include #{target_type} not readable: #{include_file})
|
926
|
-
|
929
|
+
replace_next_line %(Unresolved directive in #{@path} - include::#{target}[#{raw_attributes}])
|
927
930
|
return true
|
928
931
|
end
|
929
932
|
advance
|
@@ -966,7 +969,7 @@ class PreprocessorReader < Reader
|
|
966
969
|
end
|
967
970
|
rescue
|
968
971
|
warn %(asciidoctor: WARNING: #{line_info}: include #{target_type} not readable: #{include_file})
|
969
|
-
|
972
|
+
replace_next_line %(Unresolved directive in #{@path} - include::#{target}[#{raw_attributes}])
|
970
973
|
return true
|
971
974
|
end
|
972
975
|
unless (missing_tags = tags.to_a - tags_found.to_a).empty?
|
@@ -978,11 +981,13 @@ class PreprocessorReader < Reader
|
|
978
981
|
end
|
979
982
|
else
|
980
983
|
begin
|
984
|
+
# NOTE read content first so that we only advance cursor if IO operation succeeds
|
985
|
+
include_content = open(include_file, 'r') {|f| f.read }
|
981
986
|
advance
|
982
|
-
push_include
|
987
|
+
push_include include_content, include_file, path, 1, attributes
|
983
988
|
rescue
|
984
989
|
warn %(asciidoctor: WARNING: #{line_info}: include #{target_type} not readable: #{include_file})
|
985
|
-
|
990
|
+
replace_next_line %(Unresolved directive in #{@path} - include::#{target}[#{raw_attributes}])
|
986
991
|
return true
|
987
992
|
end
|
988
993
|
end
|
@@ -1005,7 +1010,7 @@ class PreprocessorReader < Reader
|
|
1005
1010
|
# data = IO.read file
|
1006
1011
|
# reader.push_include data, file, path
|
1007
1012
|
#
|
1008
|
-
# Returns nothing
|
1013
|
+
# Returns nothing.
|
1009
1014
|
def push_include data, file = nil, path = nil, lineno = 1, attributes = {}
|
1010
1015
|
@include_stack << [@lines, @file, @dir, @path, @lineno, @maxdepth, @process_lines]
|
1011
1016
|
if file
|
@@ -1075,7 +1080,7 @@ class PreprocessorReader < Reader
|
|
1075
1080
|
end
|
1076
1081
|
|
1077
1082
|
def include_depth
|
1078
|
-
@include_stack.size
|
1083
|
+
@include_stack.size
|
1079
1084
|
end
|
1080
1085
|
|
1081
1086
|
def exceeded_max_depth?
|
data/lib/asciidoctor/section.rb
CHANGED
@@ -95,9 +95,9 @@ class Section < AbstractBlock
|
|
95
95
|
gen_id = base_id
|
96
96
|
cnt = Compliance.unique_id_start_index
|
97
97
|
while @document.references[:ids].has_key? gen_id
|
98
|
-
gen_id =
|
98
|
+
gen_id = %(#{base_id}#{sep}#{cnt})
|
99
99
|
cnt += 1
|
100
|
-
end
|
100
|
+
end
|
101
101
|
gen_id
|
102
102
|
else
|
103
103
|
nil
|
@@ -150,9 +150,9 @@ class Section < AbstractBlock
|
|
150
150
|
def sectnum(delimiter = '.', append = nil)
|
151
151
|
append ||= (append == false ? '' : delimiter)
|
152
152
|
if @level && @level > 1 && @parent && @parent.context == :section
|
153
|
-
|
153
|
+
%(#{@parent.sectnum(delimiter)}#{@number}#{append})
|
154
154
|
else
|
155
|
-
|
155
|
+
%(#{@number}#{append})
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
@@ -162,12 +162,10 @@ class Section < AbstractBlock
|
|
162
162
|
#
|
163
163
|
# block - The child Block to append to this parent Block
|
164
164
|
#
|
165
|
-
# Returns
|
165
|
+
# Returns The parent Block
|
166
166
|
def << block
|
167
|
+
assign_index block if block.context == :section
|
167
168
|
super
|
168
|
-
if block.context == :section
|
169
|
-
assign_index block
|
170
|
-
end
|
171
169
|
end
|
172
170
|
|
173
171
|
def to_s
|
data/lib/asciidoctor/table.rb
CHANGED
@@ -42,7 +42,7 @@ class Table < AbstractBlock
|
|
42
42
|
'v' => :verse,
|
43
43
|
'a' => :asciidoc
|
44
44
|
}
|
45
|
-
|
45
|
+
|
46
46
|
# Public: A Hash mapping alignment abbreviations to alignments (horizontal
|
47
47
|
# and vertial) that can be applies to a table column or cell
|
48
48
|
ALIGNMENTS = {
|
@@ -99,21 +99,45 @@ class Table < AbstractBlock
|
|
99
99
|
# Internal: Creates the Column objects from the column spec
|
100
100
|
#
|
101
101
|
# returns nothing
|
102
|
-
def create_columns
|
103
|
-
total_width = 0
|
102
|
+
def create_columns col_specs
|
104
103
|
cols = []
|
104
|
+
width_base = 0
|
105
105
|
col_specs.each do |col_spec|
|
106
|
-
|
107
|
-
cols << Column.new
|
106
|
+
width_base += col_spec['width']
|
107
|
+
cols << (Column.new self, cols.size, col_spec)
|
108
108
|
end
|
109
|
-
|
110
|
-
unless cols.empty?
|
109
|
+
unless (@columns = cols).empty?
|
111
110
|
@attributes['colcount'] = cols.size
|
112
|
-
|
113
|
-
|
111
|
+
assign_col_widths(width_base == 0 ? nil : width_base)
|
112
|
+
end
|
113
|
+
nil
|
114
|
+
end
|
115
|
+
|
116
|
+
# Internal: Assign column widths to columns
|
117
|
+
#
|
118
|
+
# This method rounds the percentage width values to 4 decimal places and
|
119
|
+
# donates the balance to the final column.
|
120
|
+
#
|
121
|
+
# This method assumes there's at least one column in the columns array.
|
122
|
+
#
|
123
|
+
# width_base - the total of the relative column values used for calculating percentage widths (default: nil)
|
124
|
+
#
|
125
|
+
# returns nothing
|
126
|
+
def assign_col_widths width_base = nil
|
127
|
+
pf = 10.0 ** 4 # precision factor (multipler / divisor) for managing precision of calculated result
|
128
|
+
total_width = col_pcwidth = 0
|
129
|
+
|
130
|
+
if width_base
|
131
|
+
@columns.each {|col| total_width += (col_pcwidth = col.assign_width nil, width_base, pf) }
|
132
|
+
else
|
133
|
+
col_pcwidth = ((100 * pf / @columns.size).to_i) / pf
|
134
|
+
col_pcwidth = col_pcwidth.to_i if col_pcwidth.to_i == col_pcwidth
|
135
|
+
@columns.each {|col| total_width += col.assign_width col_pcwidth }
|
114
136
|
end
|
115
137
|
|
116
|
-
|
138
|
+
# donate balance, if any, to final column
|
139
|
+
@columns[-1].assign_width(((100 - total_width + col_pcwidth) * pf).round / pf) unless total_width == 100
|
140
|
+
|
117
141
|
nil
|
118
142
|
end
|
119
143
|
|
@@ -139,7 +163,7 @@ class Table < AbstractBlock
|
|
139
163
|
if num_body_rows > 0 && attributes.key?('footer-option')
|
140
164
|
@rows.foot = [@rows.body.pop]
|
141
165
|
end
|
142
|
-
|
166
|
+
|
143
167
|
nil
|
144
168
|
end
|
145
169
|
end
|
@@ -167,19 +191,18 @@ class Table::Column < AbstractNode
|
|
167
191
|
#
|
168
192
|
# This method assigns the colpcwidth and colabswidth attributes.
|
169
193
|
#
|
170
|
-
# returns
|
171
|
-
def assign_width
|
172
|
-
if
|
173
|
-
|
174
|
-
|
175
|
-
width = even_width
|
194
|
+
# returns the resolved colpcwidth value
|
195
|
+
def assign_width col_pcwidth, width_base = nil, pf = 10000.0
|
196
|
+
if width_base
|
197
|
+
col_pcwidth = ((@attributes['width'].to_f / width_base) * 100 * pf).to_i / pf
|
198
|
+
col_pcwidth = col_pcwidth.to_i if col_pcwidth.to_i == col_pcwidth
|
176
199
|
end
|
177
|
-
@attributes['colpcwidth'] =
|
200
|
+
@attributes['colpcwidth'] = col_pcwidth
|
178
201
|
if parent.attributes.key? 'tableabswidth'
|
179
|
-
|
202
|
+
# FIXME calculate more accurately (only used in DocBook output)
|
203
|
+
@attributes['colabswidth'] = ((col_pcwidth / 100.0) * parent.attributes['tableabswidth']).round
|
180
204
|
end
|
181
|
-
|
182
|
-
nil
|
205
|
+
col_pcwidth
|
183
206
|
end
|
184
207
|
end
|
185
208
|
|
@@ -348,7 +371,7 @@ class Table::ParserContext
|
|
348
371
|
|
349
372
|
# Public: Determines whether the buffer has unclosed quotes. Used for CSV data.
|
350
373
|
#
|
351
|
-
# returns true if the buffer has unclosed quotes, false if it doesn't or it
|
374
|
+
# returns true if the buffer has unclosed quotes, false if it doesn't or it
|
352
375
|
# isn't quoted data
|
353
376
|
def buffer_has_unclosed_quotes?(append = nil)
|
354
377
|
record = %(#{@buffer}#{append}).strip
|
@@ -455,7 +478,7 @@ class Table::ParserContext
|
|
455
478
|
# unquote
|
456
479
|
cell_text = cell_text[1...-1].strip
|
457
480
|
end
|
458
|
-
|
481
|
+
|
459
482
|
# collapses escaped quotes
|
460
483
|
cell_text = cell_text.tr_s('"', '"')
|
461
484
|
end
|