asciidoctor 2.0.15 → 2.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +86 -11
- data/LICENSE +1 -1
- data/README-de.adoc +9 -12
- data/README-fr.adoc +9 -12
- data/README-jp.adoc +10 -13
- data/README-zh_CN.adoc +9 -12
- data/README.adoc +33 -18
- data/asciidoctor.gemspec +2 -9
- data/data/locale/attributes-fr.adoc +2 -2
- data/data/locale/attributes-th.adoc +23 -0
- data/data/locale/attributes-vi.adoc +23 -0
- data/data/stylesheets/asciidoctor-default.css +54 -53
- data/data/stylesheets/coderay-asciidoctor.css +9 -9
- data/lib/asciidoctor/abstract_block.rb +11 -9
- data/lib/asciidoctor/abstract_node.rb +9 -8
- data/lib/asciidoctor/block.rb +6 -6
- data/lib/asciidoctor/cli/invoker.rb +1 -2
- data/lib/asciidoctor/cli/options.rb +25 -25
- data/lib/asciidoctor/convert.rb +1 -0
- data/lib/asciidoctor/converter/docbook5.rb +20 -22
- data/lib/asciidoctor/converter/html5.rb +112 -94
- data/lib/asciidoctor/converter/manpage.rb +61 -52
- data/lib/asciidoctor/converter/template.rb +12 -13
- data/lib/asciidoctor/converter.rb +6 -4
- data/lib/asciidoctor/core_ext/hash/merge.rb +1 -1
- data/lib/asciidoctor/document.rb +39 -41
- data/lib/asciidoctor/extensions.rb +20 -12
- data/lib/asciidoctor/list.rb +2 -6
- data/lib/asciidoctor/load.rb +10 -9
- data/lib/asciidoctor/logging.rb +10 -8
- data/lib/asciidoctor/parser.rb +172 -189
- data/lib/asciidoctor/path_resolver.rb +3 -3
- data/lib/asciidoctor/reader.rb +71 -72
- data/lib/asciidoctor/rx.rb +3 -2
- data/lib/asciidoctor/section.rb +7 -0
- data/lib/asciidoctor/substitutors.rb +101 -103
- data/lib/asciidoctor/syntax_highlighter/coderay.rb +2 -1
- data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +1 -1
- data/lib/asciidoctor/syntax_highlighter/pygments.rb +14 -5
- data/lib/asciidoctor/syntax_highlighter/rouge.rb +2 -1
- data/lib/asciidoctor/syntax_highlighter.rb +8 -11
- data/lib/asciidoctor/table.rb +18 -20
- data/lib/asciidoctor/timings.rb +3 -3
- data/lib/asciidoctor/version.rb +1 -1
- data/lib/asciidoctor.rb +7 -7
- data/man/asciidoctor.1 +26 -28
- data/man/asciidoctor.adoc +33 -27
- metadata +8 -62
@@ -109,7 +109,7 @@ class PathResolver
|
|
109
109
|
SLASH = '/'
|
110
110
|
BACKSLASH = '\\'
|
111
111
|
DOUBLE_SLASH = '//'
|
112
|
-
WindowsRootRx =
|
112
|
+
WindowsRootRx = %r(^(?:[a-zA-Z]:)?[\\/])
|
113
113
|
|
114
114
|
attr_accessor :file_separator
|
115
115
|
attr_accessor :working_dir
|
@@ -290,8 +290,8 @@ class PathResolver
|
|
290
290
|
# ex. ./sample/path
|
291
291
|
elsif posix_path.start_with? DOT_SLASH
|
292
292
|
root = DOT_SLASH
|
293
|
-
# else ex. sample/path
|
294
293
|
end
|
294
|
+
# otherwise ex. sample/path
|
295
295
|
elsif root? posix_path
|
296
296
|
# ex. //sample/path
|
297
297
|
if unc? posix_path
|
@@ -306,8 +306,8 @@ class PathResolver
|
|
306
306
|
# ex. ./sample/path
|
307
307
|
elsif posix_path.start_with? DOT_SLASH
|
308
308
|
root = DOT_SLASH
|
309
|
-
# else ex. sample/path
|
310
309
|
end
|
310
|
+
# otherwise ex. sample/path
|
311
311
|
|
312
312
|
path_segments = (root ? (posix_path.slice root.length, posix_path.length) : posix_path).split SLASH
|
313
313
|
# strip out all dot entries
|
data/lib/asciidoctor/reader.rb
CHANGED
@@ -59,8 +59,7 @@ class Reader
|
|
59
59
|
end
|
60
60
|
@lineno = cursor.lineno || 1
|
61
61
|
end
|
62
|
-
@lines = prepare_lines data, opts
|
63
|
-
@source_lines = @lines.drop 0
|
62
|
+
@lines = (@source_lines = prepare_lines data, opts).reverse
|
64
63
|
@mark = nil
|
65
64
|
@look_ahead = 0
|
66
65
|
@process_lines = true
|
@@ -127,7 +126,7 @@ class Reader
|
|
127
126
|
# Returns nothing if there is no more data.
|
128
127
|
def peek_line direct = false
|
129
128
|
if direct || @look_ahead > 0
|
130
|
-
@unescape_next_line ? ((line = @lines[
|
129
|
+
@unescape_next_line ? ((line = @lines[-1]).slice 1, line.length) : @lines[-1]
|
131
130
|
elsif @lines.empty?
|
132
131
|
@look_ahead = 0
|
133
132
|
nil
|
@@ -135,7 +134,7 @@ class Reader
|
|
135
134
|
# FIXME the problem with this approach is that we aren't
|
136
135
|
# retaining the modified line (hence the @unescape_next_line tweak)
|
137
136
|
# perhaps we need a stack of proxied lines
|
138
|
-
(
|
137
|
+
(process_line @lines[-1]) || peek_line
|
139
138
|
end
|
140
139
|
end
|
141
140
|
|
@@ -192,9 +191,7 @@ class Reader
|
|
192
191
|
def read_lines
|
193
192
|
lines = []
|
194
193
|
# has_more_lines? triggers preprocessor
|
195
|
-
while has_more_lines?
|
196
|
-
lines << shift
|
197
|
-
end
|
194
|
+
lines << shift while has_more_lines?
|
198
195
|
lines
|
199
196
|
end
|
200
197
|
alias readlines read_lines
|
@@ -241,7 +238,6 @@ class Reader
|
|
241
238
|
# Returns nothing.
|
242
239
|
def unshift_lines lines_to_restore
|
243
240
|
unshift_all lines_to_restore
|
244
|
-
nil
|
245
241
|
end
|
246
242
|
alias restore_lines unshift_lines
|
247
243
|
|
@@ -334,7 +330,7 @@ class Reader
|
|
334
330
|
comment_lines = []
|
335
331
|
# optimized code for shortest execution path
|
336
332
|
while (next_line = peek_line) && !next_line.empty?
|
337
|
-
if
|
333
|
+
if next_line.start_with? '//'
|
338
334
|
comment_lines << shift
|
339
335
|
else
|
340
336
|
break
|
@@ -407,34 +403,22 @@ class Reader
|
|
407
403
|
break_on_list_continuation = options[:break_on_list_continuation]
|
408
404
|
end
|
409
405
|
skip_comments = options[:skip_line_comments]
|
410
|
-
|
406
|
+
line_read = line_restored = nil
|
411
407
|
shift if options[:skip_first_line]
|
412
|
-
while
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
if break_on_list_continuation && line_read && line == LIST_CONTINUATION
|
418
|
-
options[:preserve_last_line] = true
|
419
|
-
break true
|
420
|
-
end
|
421
|
-
break true if block_given? && (yield line)
|
422
|
-
break false
|
423
|
-
end
|
424
|
-
if complete
|
425
|
-
if options[:read_last_line]
|
426
|
-
result << line
|
427
|
-
line_read = true
|
428
|
-
end
|
408
|
+
while (line = read_line)
|
409
|
+
if terminator ? line == terminator : ((break_on_blank_lines && line.empty?) ||
|
410
|
+
(break_on_list_continuation && line_read && line == LIST_CONTINUATION && (options[:preserve_last_line] = true)) ||
|
411
|
+
(block_given? && (yield line)))
|
412
|
+
result << line if options[:read_last_line]
|
429
413
|
if options[:preserve_last_line]
|
430
414
|
unshift line
|
431
415
|
line_restored = true
|
432
416
|
end
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
417
|
+
break
|
418
|
+
end
|
419
|
+
unless skip_comments && (line.start_with? '//') && !(line.start_with? '///')
|
420
|
+
result << line
|
421
|
+
line_read = true
|
438
422
|
end
|
439
423
|
end
|
440
424
|
if restore_process_lines
|
@@ -459,21 +443,37 @@ class Reader
|
|
459
443
|
def shift
|
460
444
|
@lineno += 1
|
461
445
|
@look_ahead -= 1 unless @look_ahead == 0
|
462
|
-
@lines.
|
446
|
+
@lines.pop
|
463
447
|
end
|
464
448
|
|
465
449
|
# Internal: Restore the line to the stack and decrement the lineno
|
466
450
|
def unshift line
|
467
451
|
@lineno -= 1
|
468
452
|
@look_ahead += 1
|
469
|
-
@lines.
|
453
|
+
@lines.push line
|
454
|
+
nil
|
470
455
|
end
|
471
456
|
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
457
|
+
if ::RUBY_ENGINE == 'jruby'
|
458
|
+
# Internal: Restore the lines to the stack and decrement the lineno
|
459
|
+
def unshift_all lines_to_restore
|
460
|
+
@lineno -= lines_to_restore.size
|
461
|
+
@look_ahead += lines_to_restore.size
|
462
|
+
if lines_to_restore.respond_to? :reverse
|
463
|
+
@lines.push(*lines_to_restore.reverse)
|
464
|
+
else
|
465
|
+
lines_to_restore.reverse_each {|it| @lines.push it }
|
466
|
+
end
|
467
|
+
nil
|
468
|
+
end
|
469
|
+
else
|
470
|
+
# Internal: Restore the lines to the stack and decrement the lineno
|
471
|
+
def unshift_all lines_to_restore
|
472
|
+
@lineno -= lines_to_restore.size
|
473
|
+
@look_ahead += lines_to_restore.size
|
474
|
+
@lines.push(*lines_to_restore.reverse)
|
475
|
+
nil
|
476
|
+
end
|
477
477
|
end
|
478
478
|
|
479
479
|
def cursor
|
@@ -516,12 +516,12 @@ class Reader
|
|
516
516
|
#
|
517
517
|
# Returns A copy of the String Array of lines remaining in this Reader
|
518
518
|
def lines
|
519
|
-
@lines.
|
519
|
+
@lines.reverse
|
520
520
|
end
|
521
521
|
|
522
522
|
# Public: Get a copy of the remaining lines managed by this Reader joined as a String
|
523
523
|
def string
|
524
|
-
@lines.join LF
|
524
|
+
@lines.reverse.join LF
|
525
525
|
end
|
526
526
|
|
527
527
|
# Public: Get the source lines for this Reader joined as a String
|
@@ -576,8 +576,7 @@ class Reader
|
|
576
576
|
# Returns A String Array of source lines. If the source data is an Array, this method returns a copy.
|
577
577
|
def prepare_lines data, opts = {}
|
578
578
|
if (normalize = opts[:normalize])
|
579
|
-
|
580
|
-
::Array === data ? (Helpers.prepare_source_array data, trim_end) : (Helpers.prepare_source_string data, trim_end)
|
579
|
+
::Array === data ? (Helpers.prepare_source_array data, normalize != :chomp) : (Helpers.prepare_source_string data, normalize != :chomp)
|
581
580
|
elsif ::Array === data
|
582
581
|
data.drop 0
|
583
582
|
elsif data
|
@@ -725,16 +724,11 @@ class PreprocessorReader < Reader
|
|
725
724
|
else
|
726
725
|
# FIXME we eventually want to handle leveloffset without affecting the lines
|
727
726
|
if attributes.key? 'leveloffset'
|
728
|
-
@lines.
|
729
|
-
|
730
|
-
@lines << ''
|
731
|
-
if (old_leveloffset = @document.attr 'leveloffset')
|
732
|
-
@lines << %(:leveloffset: #{old_leveloffset})
|
733
|
-
else
|
734
|
-
@lines << ':leveloffset!:'
|
735
|
-
end
|
736
|
-
# compensate for these extra lines
|
727
|
+
@lines = [((leveloffset = @document.attr 'leveloffset') ? %(:leveloffset: #{leveloffset}) : ':leveloffset!:'), ''] + @lines.reverse + ['', %(:leveloffset: #{attributes['leveloffset']})]
|
728
|
+
# compensate for these extra lines at the top
|
737
729
|
@lineno -= 2
|
730
|
+
else
|
731
|
+
@lines.reverse!
|
738
732
|
end
|
739
733
|
|
740
734
|
# FIXME kind of a hack
|
@@ -804,10 +798,8 @@ class PreprocessorReader < Reader
|
|
804
798
|
result = super
|
805
799
|
|
806
800
|
# QUESTION should this work for AsciiDoc table cell content? Currently it does not.
|
807
|
-
if @document && @document.attributes['skip-front-matter']
|
808
|
-
|
809
|
-
@document.attributes['front-matter'] = front_matter.join LF
|
810
|
-
end
|
801
|
+
if @document && @document.attributes['skip-front-matter'] && (front_matter = skip_front_matter! result)
|
802
|
+
@document.attributes['front-matter'] = front_matter.join LF
|
811
803
|
end
|
812
804
|
|
813
805
|
if opts.fetch :condense, true
|
@@ -957,11 +949,12 @@ class PreprocessorReader < Reader
|
|
957
949
|
if no_target
|
958
950
|
# the text in brackets must match a conditional expression
|
959
951
|
if text && EvalExpressionRx =~ text.strip
|
952
|
+
# NOTE assignments must happen before call to resolve_expr_val for compatibility with Opal
|
960
953
|
lhs = $1
|
954
|
+
# regex enforces a restricted set of math-related operations (==, !=, <=, >=, <, >)
|
961
955
|
op = $2
|
962
956
|
rhs = $3
|
963
|
-
|
964
|
-
skip = ((resolve_expr_val lhs).send op, (resolve_expr_val rhs)) ? false : true
|
957
|
+
skip = ((resolve_expr_val lhs).send op, (resolve_expr_val rhs)) ? false : true rescue true
|
965
958
|
else
|
966
959
|
logger.error message_with_context %(malformed preprocessor directive - #{text ? 'invalid expression' : 'missing expression'}: ifeval::[#{text}]), source_location: cursor
|
967
960
|
return true
|
@@ -1051,10 +1044,11 @@ class PreprocessorReader < Reader
|
|
1051
1044
|
|
1052
1045
|
parsed_attrs = doc.parse_attributes attrlist, [], sub_input: true
|
1053
1046
|
inc_path, target_type, relpath = resolve_include_path expanded_target, attrlist, parsed_attrs
|
1054
|
-
|
1047
|
+
case target_type
|
1048
|
+
when :file
|
1055
1049
|
reader = ::File.method :open
|
1056
1050
|
read_mode = FILE_READ_MODE
|
1057
|
-
|
1051
|
+
when :uri
|
1058
1052
|
reader = ::OpenURI.method :open_uri
|
1059
1053
|
read_mode = URI_READ_MODE
|
1060
1054
|
else
|
@@ -1075,7 +1069,7 @@ class PreprocessorReader < Reader
|
|
1075
1069
|
(split_delimited_value parsed_attrs['lines']).each do |linedef|
|
1076
1070
|
if linedef.include? '..'
|
1077
1071
|
from, _, to = linedef.partition '..'
|
1078
|
-
inc_linenos += (to.empty? || (to = to.to_i) < 0) ? [from.to_i,
|
1072
|
+
inc_linenos += (to.empty? || (to = to.to_i) < 0) ? [from.to_i, ::Float::INFINITY] : (from.to_i..to).to_a
|
1079
1073
|
else
|
1080
1074
|
inc_linenos << linedef.to_i
|
1081
1075
|
end
|
@@ -1131,18 +1125,23 @@ class PreprocessorReader < Reader
|
|
1131
1125
|
push_include inc_lines, inc_path, relpath, inc_offset, parsed_attrs
|
1132
1126
|
end
|
1133
1127
|
elsif inc_tags
|
1134
|
-
inc_lines, inc_offset, inc_lineno, tag_stack,
|
1128
|
+
inc_lines, inc_offset, inc_lineno, tag_stack, tags_selected, active_tag = [], nil, 0, [], ::Set.new, nil
|
1135
1129
|
if inc_tags.key? '**'
|
1130
|
+
select = base_select = inc_tags.delete '**'
|
1136
1131
|
if inc_tags.key? '*'
|
1137
|
-
select = base_select = inc_tags.delete '**'
|
1138
1132
|
wildcard = inc_tags.delete '*'
|
1139
|
-
|
1140
|
-
|
1133
|
+
elsif !select && inc_tags.values.first == false
|
1134
|
+
wildcard = true
|
1141
1135
|
end
|
1142
1136
|
elsif inc_tags.key? '*'
|
1143
|
-
|
1137
|
+
if inc_tags.keys.first == '*'
|
1138
|
+
select = base_select = !(wildcard = inc_tags.delete '*')
|
1139
|
+
else
|
1140
|
+
select = base_select = false
|
1141
|
+
wildcard = inc_tags.delete '*'
|
1142
|
+
end
|
1144
1143
|
else
|
1145
|
-
select = base_select =
|
1144
|
+
select = base_select = !(inc_tags.value? true)
|
1146
1145
|
end
|
1147
1146
|
begin
|
1148
1147
|
reader.call inc_path, read_mode do |f|
|
@@ -1165,9 +1164,9 @@ class PreprocessorReader < Reader
|
|
1165
1164
|
end
|
1166
1165
|
end
|
1167
1166
|
elsif inc_tags.key? this_tag
|
1168
|
-
|
1167
|
+
tags_selected << this_tag if (select = inc_tags[this_tag])
|
1169
1168
|
# QUESTION should we prevent tag from being selected when enclosing tag is excluded?
|
1170
|
-
tag_stack << [(active_tag = this_tag),
|
1169
|
+
tag_stack << [(active_tag = this_tag), select, inc_lineno]
|
1171
1170
|
elsif !wildcard.nil?
|
1172
1171
|
select = active_tag && !select ? false : wildcard
|
1173
1172
|
tag_stack << [(active_tag = this_tag), select, inc_lineno]
|
@@ -1188,12 +1187,12 @@ class PreprocessorReader < Reader
|
|
1188
1187
|
logger.warn message_with_context %(detected unclosed tag '#{tag_name}' starting at line #{tag_lineno} of include #{target_type}: #{inc_path}), source_location: cursor, include_location: (create_include_cursor inc_path, expanded_target, tag_lineno)
|
1189
1188
|
end
|
1190
1189
|
end
|
1191
|
-
unless (missing_tags = inc_tags.keys -
|
1190
|
+
unless (missing_tags = inc_tags.keep_if {|_, v| v }.keys - tags_selected.to_a).empty?
|
1192
1191
|
logger.warn message_with_context %(tag#{missing_tags.size > 1 ? 's' : ''} '#{missing_tags.join ', '}' not found in include #{target_type}: #{inc_path}), source_location: cursor
|
1193
1192
|
end
|
1194
1193
|
shift
|
1195
1194
|
if inc_offset
|
1196
|
-
parsed_attrs['partial-option'] = '' unless base_select && wildcard && inc_tags.empty?
|
1195
|
+
parsed_attrs['partial-option'] = '' unless base_select && wildcard != false && inc_tags.empty?
|
1197
1196
|
# FIXME not accounting for skipped lines in reader line numbering
|
1198
1197
|
push_include inc_lines, inc_path, relpath, inc_offset, parsed_attrs
|
1199
1198
|
end
|
@@ -1264,7 +1263,7 @@ class PreprocessorReader < Reader
|
|
1264
1263
|
end
|
1265
1264
|
|
1266
1265
|
def pop_include
|
1267
|
-
|
1266
|
+
unless @include_stack.empty?
|
1268
1267
|
@lines, @file, @dir, @path, @lineno, @maxdepth, @process_lines = @include_stack.pop
|
1269
1268
|
# FIXME kind of a hack
|
1270
1269
|
#Document::AttributeEntry.new('infile', @file).save_to_next_block @document
|
data/lib/asciidoctor/rx.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Asciidoctor
|
2
3
|
# A collection of regular expression constants used by the parser. (For speed, these are not defined in the Rx module,
|
3
4
|
# but rather directly in the Asciidoctor module).
|
@@ -406,7 +407,7 @@ module Asciidoctor
|
|
406
407
|
# gist::123456[]
|
407
408
|
#
|
408
409
|
#--
|
409
|
-
# NOTE we've relaxed the match for target to
|
410
|
+
# NOTE we've relaxed the match for target to accommodate the short format (e.g., name::[attrlist])
|
410
411
|
CustomBlockMacroRx = /^(#{CG_WORD}[#{CC_WORD}-]*)::(|\S|\S#{CC_ANY}*?\S)\[(#{CC_ANY}+)?\]$/
|
411
412
|
|
412
413
|
# Matches an image, video or audio block macro.
|
@@ -469,7 +470,7 @@ module Asciidoctor
|
|
469
470
|
# footnoteref:[id,text] (legacy)
|
470
471
|
# footnoteref:[id] (legacy)
|
471
472
|
#
|
472
|
-
InlineFootnoteMacroRx =
|
473
|
+
InlineFootnoteMacroRx = %r(\\?footnote(?:(ref):|:([#{CC_WORD}-]+)?)\[(?:|(#{CC_ALL}*?[^\\]))\](?!</a>))m
|
473
474
|
|
474
475
|
# Matches an image or icon inline macro.
|
475
476
|
#
|
data/lib/asciidoctor/section.rb
CHANGED
@@ -64,6 +64,13 @@ class Section < AbstractBlock
|
|
64
64
|
Section.generate_id title, @document
|
65
65
|
end
|
66
66
|
|
67
|
+
# Public: Check whether this Section has any child Section objects.
|
68
|
+
#
|
69
|
+
# Returns A [Boolean] to indicate whether this Section has child Section objects
|
70
|
+
def sections?
|
71
|
+
@next_section_index > 0
|
72
|
+
end
|
73
|
+
|
67
74
|
# Public: Get the section number for the current Section
|
68
75
|
#
|
69
76
|
# The section number is a dot-separated String that uniquely describes the position of this
|