asciidoctor 2.0.13 → 2.0.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +151 -30
- 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 +40 -19
- 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/attribute_list.rb +1 -1
- 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 +45 -26
- data/lib/asciidoctor/converter/html5.rb +130 -102
- data/lib/asciidoctor/converter/manpage.rb +69 -64
- 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 +61 -57
- data/lib/asciidoctor/extensions.rb +20 -12
- data/lib/asciidoctor/list.rb +2 -6
- data/lib/asciidoctor/load.rb +11 -9
- data/lib/asciidoctor/logging.rb +10 -8
- data/lib/asciidoctor/parser.rb +177 -193
- data/lib/asciidoctor/path_resolver.rb +3 -3
- data/lib/asciidoctor/reader.rb +73 -72
- data/lib/asciidoctor/rx.rb +5 -4
- data/lib/asciidoctor/section.rb +7 -0
- data/lib/asciidoctor/substitutors.rb +121 -121
- 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 +16 -7
- 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 +10 -10
- data/man/asciidoctor.1 +26 -28
- data/man/asciidoctor.adoc +33 -27
- metadata +8 -62
@@ -40,13 +40,13 @@ class Converter::TemplateConverter < Converter::Base
|
|
40
40
|
@caches = { scans: {}, templates: {} }
|
41
41
|
end
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
end
|
43
|
+
class << self
|
44
|
+
attr_reader :caches
|
46
45
|
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
def clear_caches
|
47
|
+
@caches[:scans].clear
|
48
|
+
@caches[:templates].clear
|
49
|
+
end
|
50
50
|
end
|
51
51
|
|
52
52
|
def initialize backend, template_dirs, opts = {}
|
@@ -134,12 +134,10 @@ class Converter::TemplateConverter < Converter::Base
|
|
134
134
|
#
|
135
135
|
# Returns the Tilt template object
|
136
136
|
def register name, template
|
137
|
-
|
137
|
+
if (template_cache = @caches[:templates])
|
138
138
|
template_cache[template.file] = template
|
139
|
-
else
|
140
|
-
template
|
141
139
|
end
|
142
|
-
|
140
|
+
@templates[name] = template
|
143
141
|
end
|
144
142
|
|
145
143
|
private
|
@@ -155,6 +153,7 @@ class Converter::TemplateConverter < Converter::Base
|
|
155
153
|
engine = @engine
|
156
154
|
@template_dirs.each do |template_dir|
|
157
155
|
# FIXME need to think about safe mode restrictions here
|
156
|
+
# Ruby 2.3 requires the extra brackets around the path_resolver.system_path method call
|
158
157
|
next unless ::File.directory?(template_dir = (path_resolver.system_path template_dir))
|
159
158
|
|
160
159
|
if engine
|
@@ -186,8 +185,8 @@ class Converter::TemplateConverter < Converter::Base
|
|
186
185
|
else
|
187
186
|
@templates.update scan_dir(template_dir, pattern, @caches[:templates])
|
188
187
|
end
|
189
|
-
nil
|
190
188
|
end
|
189
|
+
nil
|
191
190
|
end
|
192
191
|
|
193
192
|
# Internal: Scan the specified directory for template files matching pattern and instantiate
|
@@ -197,7 +196,7 @@ class Converter::TemplateConverter < Converter::Base
|
|
197
196
|
def scan_dir template_dir, pattern, template_cache = nil
|
198
197
|
result, helpers = {}, nil
|
199
198
|
# Grab the files in the top level of the directory (do not recurse)
|
200
|
-
::Dir.glob(pattern).
|
199
|
+
::Dir.glob(pattern).keep_if {|match| ::File.file? match }.each do |file|
|
201
200
|
if (basename = ::File.basename file) == 'helpers.rb'
|
202
201
|
helpers = file
|
203
202
|
next
|
@@ -262,7 +261,7 @@ class Converter::TemplateConverter < Converter::Base
|
|
262
261
|
[::Tilt::ErubiTemplate, {}]
|
263
262
|
elsif name == 'erubis'
|
264
263
|
Helpers.require_library 'erubis' unless defined? ::Erubis::FastEruby
|
265
|
-
[::Tilt::ErubisTemplate,
|
264
|
+
[::Tilt::ErubisTemplate, engine_class: ::Erubis::FastEruby]
|
266
265
|
else
|
267
266
|
raise ::ArgumentError, %(Unknown ERB implementation: #{name})
|
268
267
|
end
|
@@ -42,7 +42,7 @@ module Asciidoctor
|
|
42
42
|
# puts Asciidoctor.convert_file 'sample.adoc', safe: :safe
|
43
43
|
module Converter
|
44
44
|
autoload :CompositeConverter, %(#{__dir__}/converter/composite)
|
45
|
-
autoload :TemplateConverter, %(#{__dir__}/converter/template)
|
45
|
+
autoload :TemplateConverter, %(#{__dir__}/converter/template) unless RUBY_ENGINE == 'opal'
|
46
46
|
|
47
47
|
# Public: The String backend name that this converter is handling.
|
48
48
|
attr_reader :backend
|
@@ -366,15 +366,17 @@ module Converter
|
|
366
366
|
# into - The Class into which the {Converter} module is being included.
|
367
367
|
#
|
368
368
|
# Returns nothing.
|
369
|
-
|
369
|
+
def self.included into
|
370
370
|
into.send :include, BackendTraits
|
371
371
|
into.extend Config
|
372
|
-
end
|
372
|
+
end
|
373
|
+
private_class_method :included # use separate declaration for Ruby 2.0.x
|
373
374
|
|
374
375
|
# An abstract base class for defining converters that can be used to convert {AbstractNode} objects in a parsed
|
375
376
|
# AsciiDoc document to a backend format such as HTML or DocBook.
|
376
377
|
class Base
|
377
|
-
include
|
378
|
+
include Logging
|
379
|
+
include Converter
|
378
380
|
|
379
381
|
# Public: Converts an {AbstractNode} by delegating to a method that matches the transform value.
|
380
382
|
#
|
@@ -3,6 +3,6 @@
|
|
3
3
|
# NOTE use `send :prepend` to be nice to Ruby 2.0
|
4
4
|
Hash.send :prepend, (Module.new do
|
5
5
|
def merge *args
|
6
|
-
(len = args.length) < 1 ?
|
6
|
+
(len = args.length) < 1 ? dup : (len > 1 ? args.inject(self) {|acc, arg| acc.merge arg } : (super args[0]))
|
7
7
|
end
|
8
8
|
end) if (Hash.instance_method :merge).arity == 1
|
data/lib/asciidoctor/document.rb
CHANGED
@@ -198,7 +198,7 @@ class Document < AbstractBlock
|
|
198
198
|
# Public: Get the document catalog Hash
|
199
199
|
attr_reader :catalog
|
200
200
|
|
201
|
-
# Public: Alias catalog property as references for backwards
|
201
|
+
# Public: Alias catalog property as references for backwards compatibility
|
202
202
|
alias references catalog
|
203
203
|
|
204
204
|
# Public: Get the Hash of document counters
|
@@ -259,12 +259,14 @@ class Document < AbstractBlock
|
|
259
259
|
options[:catalog_assets] = true if parent_doc.options[:catalog_assets]
|
260
260
|
@catalog = parent_doc.catalog.merge footnotes: []
|
261
261
|
# QUESTION should we support setting attribute in parent document from nested document?
|
262
|
-
|
263
|
-
@attribute_overrides = attr_overrides = parent_doc.attributes.merge
|
264
|
-
parent_doctype = attr_overrides.delete 'doctype'
|
262
|
+
@attribute_overrides = attr_overrides = (parent_doc.instance_variable_get :@attribute_overrides).merge parent_doc.attributes
|
265
263
|
attr_overrides.delete 'compat-mode'
|
264
|
+
parent_doctype = attr_overrides.delete 'doctype'
|
265
|
+
attr_overrides.delete 'notitle'
|
266
|
+
attr_overrides.delete 'showtitle'
|
267
|
+
# QUESTION if toc is hard unset in parent document, should it be hard unset in nested document?
|
266
268
|
attr_overrides.delete 'toc'
|
267
|
-
attr_overrides.delete 'toc-placement'
|
269
|
+
@attributes['toc-placement'] = (attr_overrides.delete 'toc-placement') || 'auto'
|
268
270
|
attr_overrides.delete 'toc-position'
|
269
271
|
@safe = parent_doc.safe
|
270
272
|
@attributes['compat-mode'] = '' if (@compat_mode = parent_doc.compat_mode)
|
@@ -284,7 +286,6 @@ class Document < AbstractBlock
|
|
284
286
|
footnotes: [],
|
285
287
|
links: [],
|
286
288
|
images: [],
|
287
|
-
#indexterms: [],
|
288
289
|
callouts: Callouts.new,
|
289
290
|
includes: {},
|
290
291
|
}
|
@@ -309,7 +310,7 @@ class Document < AbstractBlock
|
|
309
310
|
end
|
310
311
|
attr_overrides[key.downcase] = val
|
311
312
|
end
|
312
|
-
if (to_file = options[:to_file])
|
313
|
+
if ::String === (to_file = options[:to_file])
|
313
314
|
attr_overrides['outfilesuffix'] = Helpers.extname to_file
|
314
315
|
end
|
315
316
|
# safely resolve the safe mode from const, int or string
|
@@ -327,7 +328,7 @@ class Document < AbstractBlock
|
|
327
328
|
@timings = options.delete :timings
|
328
329
|
@path_resolver = PathResolver.new
|
329
330
|
initialize_extensions = (defined? ::Asciidoctor::Extensions) || (options.key? :extensions) ? ::Asciidoctor::Extensions : nil
|
330
|
-
@extensions = nil # initialize
|
331
|
+
@extensions = nil # initialize further down if initialize_extensions is true
|
331
332
|
options[:standalone] = options[:header_footer] if (options.key? :header_footer) && !(options.key? :standalone)
|
332
333
|
end
|
333
334
|
|
@@ -339,11 +340,13 @@ class Document < AbstractBlock
|
|
339
340
|
(@options = options).freeze
|
340
341
|
|
341
342
|
attrs = @attributes
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
343
|
+
unless parent_doc
|
344
|
+
attrs['attribute-undefined'] = Compliance.attribute_undefined
|
345
|
+
attrs['attribute-missing'] = Compliance.attribute_missing
|
346
|
+
attrs.update DEFAULT_ATTRIBUTES
|
347
|
+
# TODO if lang attribute is set, @safe mode < SafeMode::SERVER, and !parent_doc,
|
348
|
+
# load attributes from data/locale/attributes-<lang>.adoc
|
349
|
+
end
|
347
350
|
|
348
351
|
if standalone
|
349
352
|
# sync embedded attribute with :standalone option value
|
@@ -356,9 +359,9 @@ class Document < AbstractBlock
|
|
356
359
|
# sync embedded attribute with :standalone option value
|
357
360
|
attr_overrides['embedded'] = ''
|
358
361
|
if (attr_overrides.key? 'showtitle') && (attr_overrides.keys & %w(notitle showtitle))[-1] == 'showtitle'
|
359
|
-
attr_overrides['notitle'] = { nil => '', false => '@', '@' => false}[attr_overrides['showtitle']]
|
362
|
+
attr_overrides['notitle'] = { nil => '', false => '@', '@' => false }[attr_overrides['showtitle']]
|
360
363
|
elsif attr_overrides.key? 'notitle'
|
361
|
-
attr_overrides['showtitle'] = { nil => '', false => '@', '@' => false}[attr_overrides['notitle']]
|
364
|
+
attr_overrides['showtitle'] = { nil => '', false => '@', '@' => false }[attr_overrides['notitle']]
|
362
365
|
else
|
363
366
|
attrs['notitle'] = ''
|
364
367
|
end
|
@@ -371,14 +374,12 @@ class Document < AbstractBlock
|
|
371
374
|
attr_overrides[%(safe-mode-#{safe_mode_name})] = ''
|
372
375
|
attr_overrides['safe-mode-level'] = @safe
|
373
376
|
|
374
|
-
# the only way to set the max-include-depth attribute is via the API; default to 64 like AsciiDoc
|
377
|
+
# the only way to set the max-include-depth attribute is via the API; default to 64 like AsciiDoc.py
|
375
378
|
attr_overrides['max-include-depth'] ||= 64
|
376
379
|
|
377
380
|
# the only way to set the allow-uri-read attribute is via the API; disabled by default
|
378
381
|
attr_overrides['allow-uri-read'] ||= nil
|
379
382
|
|
380
|
-
attr_overrides['user-home'] = USER_HOME
|
381
|
-
|
382
383
|
# remap legacy attribute names
|
383
384
|
attr_overrides['sectnums'] = attr_overrides.delete 'numbered' if attr_overrides.key? 'numbered'
|
384
385
|
attr_overrides['hardbreaks-option'] = attr_overrides.delete 'hardbreaks' if attr_overrides.key? 'hardbreaks'
|
@@ -397,11 +398,11 @@ class Document < AbstractBlock
|
|
397
398
|
|
398
399
|
# allow common attributes backend and doctype to be set using options hash, coerce values to string
|
399
400
|
if (backend_val = options[:backend])
|
400
|
-
attr_overrides['backend'] =
|
401
|
+
attr_overrides['backend'] = backend_val.to_s
|
401
402
|
end
|
402
403
|
|
403
404
|
if (doctype_val = options[:doctype])
|
404
|
-
attr_overrides['doctype'] =
|
405
|
+
attr_overrides['doctype'] = doctype_val.to_s
|
405
406
|
end
|
406
407
|
|
407
408
|
if @safe >= SafeMode::SERVER
|
@@ -414,7 +415,7 @@ class Document < AbstractBlock
|
|
414
415
|
attr_overrides['docfile'] = attr_overrides['docfile'][(attr_overrides['docdir'].length + 1)..-1]
|
415
416
|
end
|
416
417
|
attr_overrides['docdir'] = ''
|
417
|
-
attr_overrides['user-home']
|
418
|
+
attr_overrides['user-home'] ||= '.'
|
418
419
|
if @safe >= SafeMode::SECURE
|
419
420
|
attr_overrides['max-attribute-value-size'] = 4096 unless attr_overrides.key? 'max-attribute-value-size'
|
420
421
|
# assign linkcss (preventing css embedding) unless explicitly disabled from the commandline or API
|
@@ -423,6 +424,8 @@ class Document < AbstractBlock
|
|
423
424
|
# restrict document from enabling icons
|
424
425
|
attr_overrides['icons'] ||= nil
|
425
426
|
end
|
427
|
+
else
|
428
|
+
attr_overrides['user-home'] ||= USER_HOME
|
426
429
|
end
|
427
430
|
|
428
431
|
# the only way to set the max-attribute-value-size attribute is via the API; disabled by default
|
@@ -562,15 +565,15 @@ class Document < AbstractBlock
|
|
562
565
|
# returns the next number in the sequence for the specified counter
|
563
566
|
def counter name, seed = nil
|
564
567
|
return @parent_document.counter name, seed if @parent_document
|
565
|
-
if attribute_locked? name
|
566
|
-
@
|
567
|
-
elsif (attr_seed = !(attr_val = @attributes[name]).nil_or_empty?) && (@counters.key? name)
|
568
|
-
@attributes[name] = @counters[name] = Helpers.nextval attr_val
|
568
|
+
if ((locked = attribute_locked? name) && (curr_val = @counters[name])) || !(curr_val = @attributes[name]).nil_or_empty?
|
569
|
+
next_val = @counters[name] = Helpers.nextval curr_val
|
569
570
|
elsif seed
|
570
|
-
|
571
|
+
next_val = @counters[name] = seed == seed.to_i.to_s ? seed.to_i : seed
|
571
572
|
else
|
572
|
-
|
573
|
+
next_val = @counters[name] = 1
|
573
574
|
end
|
575
|
+
@attributes[name] = next_val unless locked
|
576
|
+
next_val
|
574
577
|
end
|
575
578
|
|
576
579
|
# Public: Increment the specified counter and store it in the block's attributes
|
@@ -612,15 +615,29 @@ class Document < AbstractBlock
|
|
612
615
|
# @reftexts is set eagerly to prevent nested lazy init
|
613
616
|
(@reftexts = {}).tap {|accum| @catalog[:refs].each {|id, ref| accum[ref.xreftext] ||= id } }[text]
|
614
617
|
else
|
615
|
-
# @reftexts is set eagerly to prevent nested lazy init
|
616
618
|
resolved_id = nil
|
617
|
-
#
|
618
|
-
|
619
|
+
# @reftexts is set eagerly to prevent nested lazy init
|
620
|
+
@reftexts = accum = {}
|
621
|
+
@catalog[:refs].each do |id, ref|
|
622
|
+
# NOTE short-circuit early since we're throwing away this table anyway
|
623
|
+
if (xreftext = ref.xreftext) == text
|
624
|
+
resolved_id = id
|
625
|
+
break
|
626
|
+
end
|
627
|
+
accum[xreftext] ||= id
|
628
|
+
end
|
619
629
|
@reftexts = nil
|
620
630
|
resolved_id
|
621
631
|
end
|
622
632
|
end
|
623
633
|
|
634
|
+
# Public: Check whether this Document has any child Section objects.
|
635
|
+
#
|
636
|
+
# Returns A [Boolean] to indicate whether this Document has child Section objects
|
637
|
+
def sections?
|
638
|
+
@next_section_index > 0
|
639
|
+
end
|
640
|
+
|
624
641
|
def footnotes?
|
625
642
|
@catalog[:footnotes].empty? ? false : true
|
626
643
|
end
|
@@ -673,7 +690,7 @@ class Document < AbstractBlock
|
|
673
690
|
#
|
674
691
|
# title - the String title to assign as the title of the document header
|
675
692
|
#
|
676
|
-
# Returns the
|
693
|
+
# Returns the specified [String] title
|
677
694
|
def title= title
|
678
695
|
unless (sect = @header)
|
679
696
|
(sect = (@header = Section.new self, 0)).sectname = 'header'
|
@@ -955,8 +972,14 @@ class Document < AbstractBlock
|
|
955
972
|
|
956
973
|
# Public: Write the output to the specified file
|
957
974
|
#
|
958
|
-
# If the converter responds to :write, delegate the work of writing the
|
959
|
-
# to that method. Otherwise, write the output the specified file.
|
975
|
+
# If the converter responds to :write, delegate the work of writing the output
|
976
|
+
# to that method. Otherwise, write the output to the specified file. In the
|
977
|
+
# latter case, this method ensures the output has a trailing newline if the
|
978
|
+
# target responds to write and the output is not empty.
|
979
|
+
#
|
980
|
+
# output - The output to write. Unless the converter responds to write, this
|
981
|
+
# object is expected to be a String.
|
982
|
+
# target - The file to write, either a File object or a String path.
|
960
983
|
#
|
961
984
|
# Returns nothing
|
962
985
|
def write output, target
|
@@ -982,25 +1005,6 @@ class Document < AbstractBlock
|
|
982
1005
|
nil
|
983
1006
|
end
|
984
1007
|
|
985
|
-
=begin
|
986
|
-
def convert_to target, opts = {}
|
987
|
-
start = ::Time.now.to_f if (monitor = opts[:monitor])
|
988
|
-
output = (r = converter opts).convert
|
989
|
-
monitor[:convert] = ::Time.now.to_f - start if monitor
|
990
|
-
|
991
|
-
unless target.respond_to? :write
|
992
|
-
@attributes['outfile'] = target = ::File.expand_path target
|
993
|
-
@attributes['outdir'] = ::File.dirname target
|
994
|
-
end
|
995
|
-
|
996
|
-
start = ::Time.now.to_f if monitor
|
997
|
-
r.write output, target
|
998
|
-
monitor[:write] = ::Time.now.to_f - start if monitor
|
999
|
-
|
1000
|
-
output
|
1001
|
-
end
|
1002
|
-
=end
|
1003
|
-
|
1004
1008
|
def content
|
1005
1009
|
# NOTE per AsciiDoc-spec, remove the title before converting the body
|
1006
1010
|
@attributes.delete('title')
|
@@ -1022,7 +1026,7 @@ class Document < AbstractBlock
|
|
1022
1026
|
def docinfo location = :head, suffix = nil
|
1023
1027
|
if safe < SafeMode::SECURE
|
1024
1028
|
qualifier = %(-#{location}) unless location == :head
|
1025
|
-
suffix
|
1029
|
+
suffix ||= @outfilesuffix
|
1026
1030
|
|
1027
1031
|
if (docinfo = @attributes['docinfo']).nil_or_empty?
|
1028
1032
|
if @attributes.key? 'docinfo2'
|
@@ -1079,7 +1083,7 @@ class Document < AbstractBlock
|
|
1079
1083
|
end
|
1080
1084
|
|
1081
1085
|
def to_s
|
1082
|
-
%(#<#{self.class}@#{object_id} {doctype: #{doctype.inspect}, doctitle: #{(@header
|
1086
|
+
%(#<#{self.class}@#{object_id} {doctype: #{doctype.inspect}, doctitle: #{(@header && @header.title).inspect}, blocks: #{@blocks.size}}>)
|
1083
1087
|
end
|
1084
1088
|
|
1085
1089
|
private
|
@@ -1208,8 +1212,8 @@ class Document < AbstractBlock
|
|
1208
1212
|
end
|
1209
1213
|
end
|
1210
1214
|
|
1211
|
-
if (@compat_mode = attrs.key? 'compat-mode')
|
1212
|
-
attrs['source-language'] = attrs['language']
|
1215
|
+
if (@compat_mode = attrs.key? 'compat-mode') && (attrs.key? 'language')
|
1216
|
+
attrs['source-language'] = attrs['language']
|
1213
1217
|
end
|
1214
1218
|
|
1215
1219
|
unless @parent_document
|
@@ -1382,7 +1386,7 @@ class Document < AbstractBlock
|
|
1382
1386
|
attrs[%(basebackend-#{current_basebackend}-doctype-#{new_doctype})] = '' if current_basebackend
|
1383
1387
|
end
|
1384
1388
|
attrs[%(doctype-#{new_doctype})] = ''
|
1385
|
-
|
1389
|
+
@doctype = attrs['doctype'] = new_doctype
|
1386
1390
|
end
|
1387
1391
|
end
|
1388
1392
|
end
|
@@ -134,14 +134,14 @@ module Extensions
|
|
134
134
|
if opts.fetch :numbered, (style == 'appendix')
|
135
135
|
sect.numbered = true
|
136
136
|
elsif !(opts.key? :numbered) && (doc.attr? 'sectnums', 'all')
|
137
|
-
sect.numbered = book && level == 1 ? :chapter : true
|
137
|
+
sect.numbered = (book && level == 1 ? :chapter : true)
|
138
138
|
end
|
139
139
|
elsif level > 0
|
140
140
|
if opts.fetch :numbered, (doc.attr? 'sectnums')
|
141
141
|
sect.numbered = sect.special ? parent.numbered && true : true
|
142
142
|
end
|
143
|
-
|
144
|
-
sect.numbered = true
|
143
|
+
elsif opts.fetch :numbered, (book && (doc.attr? 'partnums'))
|
144
|
+
sect.numbered = true
|
145
145
|
end
|
146
146
|
if (id = attrs['id']) == false
|
147
147
|
attrs.delete 'id'
|
@@ -229,7 +229,7 @@ module Extensions
|
|
229
229
|
def parse_attributes block, attrlist, opts = {}
|
230
230
|
return {} if attrlist ? attrlist.empty? : true
|
231
231
|
attrlist = block.sub_attributes attrlist if opts[:sub_attributes] && (attrlist.include? ATTR_REF_HEAD)
|
232
|
-
(AttributeList.new attrlist).parse
|
232
|
+
(AttributeList.new attrlist).parse opts[:positional_attributes] || []
|
233
233
|
end
|
234
234
|
|
235
235
|
# TODO fill out remaining methods
|
@@ -511,6 +511,10 @@ module Extensions
|
|
511
511
|
# registered to handle this name and, if found, invokes its {Processor#process}
|
512
512
|
# method to build a corresponding node in the document tree.
|
513
513
|
#
|
514
|
+
# If the process method returns an instance of Block, the content model of that
|
515
|
+
# Block is :compound, and the Block contains at least one line, the parser will
|
516
|
+
# parse those lines into blocks an assigned them to the returned block.
|
517
|
+
#
|
514
518
|
# AsciiDoc example:
|
515
519
|
#
|
516
520
|
# [shout]
|
@@ -594,6 +598,10 @@ module Extensions
|
|
594
598
|
# Public: BlockMacroProcessors are used to handle block macros that have a
|
595
599
|
# custom name.
|
596
600
|
#
|
601
|
+
# If the process method returns an instance of Block, the content model of that
|
602
|
+
# Block is :compound, and the Block contains at least one line, the parser will
|
603
|
+
# parse those lines into blocks an assigned them to the returned block.
|
604
|
+
#
|
597
605
|
# BlockMacroProcessor implementations must extend BlockMacroProcessor.
|
598
606
|
class BlockMacroProcessor < MacroProcessor
|
599
607
|
def name
|
@@ -666,7 +674,7 @@ module Extensions
|
|
666
674
|
|
667
675
|
# Public: A specialization of the Extension proxy that additionally stores a
|
668
676
|
# reference to the {Processor#process} method. By storing this reference, its
|
669
|
-
# possible to
|
677
|
+
# possible to accommodate both concrete extension implementations and Procs.
|
670
678
|
class ProcessorExtension < Extension
|
671
679
|
attr_reader :process_method
|
672
680
|
|
@@ -954,7 +962,7 @@ module Extensions
|
|
954
962
|
end
|
955
963
|
|
956
964
|
# Public: Registers an {DocinfoProcessor} with the extension registry to
|
957
|
-
# add
|
965
|
+
# add additional docinfo to the document.
|
958
966
|
#
|
959
967
|
# The DocinfoProcessor may be one of four types:
|
960
968
|
#
|
@@ -1199,7 +1207,7 @@ module Extensions
|
|
1199
1207
|
# name - the String or Symbol (coersed to a Symbol) macro name
|
1200
1208
|
#
|
1201
1209
|
# Returns the [Extension] object stored in the registry that proxies the
|
1202
|
-
#
|
1210
|
+
# corresponding BlockMacroProcessor or nil if a match is not found.
|
1203
1211
|
def find_block_macro_extension name
|
1204
1212
|
@block_macro_extensions[name.to_sym]
|
1205
1213
|
end
|
@@ -1286,7 +1294,7 @@ module Extensions
|
|
1286
1294
|
# name - the String or Symbol (coersed to a Symbol) macro name
|
1287
1295
|
#
|
1288
1296
|
# Returns the [Extension] object stored in the registry that proxies the
|
1289
|
-
#
|
1297
|
+
# corresponding InlineMacroProcessor or nil if a match is not found.
|
1290
1298
|
def find_inline_macro_extension name
|
1291
1299
|
@inline_macro_extensions[name.to_sym]
|
1292
1300
|
end
|
@@ -1328,7 +1336,7 @@ module Extensions
|
|
1328
1336
|
kind_java_class = (defined? ::AsciidoctorJ) ? (::AsciidoctorJ::Extensions.const_get kind_class_symbol, false) : nil
|
1329
1337
|
kind_store = instance_variable_get(%(@#{kind}_extensions).to_sym) || instance_variable_set(%(@#{kind}_extensions).to_sym, [])
|
1330
1338
|
# style 1: specified as block
|
1331
|
-
|
1339
|
+
if block_given?
|
1332
1340
|
config = resolve_args args, 1
|
1333
1341
|
(processor = kind_class.new config).singleton_class.enable_dsl
|
1334
1342
|
if block.arity == 0
|
@@ -1340,7 +1348,7 @@ module Extensions
|
|
1340
1348
|
raise ::ArgumentError, %(No block specified to process #{kind_name} extension at #{block.source_location})
|
1341
1349
|
end
|
1342
1350
|
processor.freeze
|
1343
|
-
ProcessorExtension.new kind, processor
|
1351
|
+
extension = ProcessorExtension.new kind, processor
|
1344
1352
|
else
|
1345
1353
|
processor, config = resolve_args args, 2
|
1346
1354
|
# style 2: specified as Class or String class name
|
@@ -1350,12 +1358,12 @@ module Extensions
|
|
1350
1358
|
end
|
1351
1359
|
processor_instance = processor_class.new config
|
1352
1360
|
processor_instance.freeze
|
1353
|
-
ProcessorExtension.new kind, processor_instance
|
1361
|
+
extension = ProcessorExtension.new kind, processor_instance
|
1354
1362
|
# style 3: specified as instance
|
1355
1363
|
elsif kind_class === processor || (kind_java_class && kind_java_class === processor)
|
1356
1364
|
processor.update_config config
|
1357
1365
|
processor.freeze
|
1358
|
-
ProcessorExtension.new kind, processor
|
1366
|
+
extension = ProcessorExtension.new kind, processor
|
1359
1367
|
else
|
1360
1368
|
raise ::ArgumentError, %(Invalid arguments specified for registering #{kind_name} extension: #{args})
|
1361
1369
|
end
|
data/lib/asciidoctor/list.rb
CHANGED
@@ -80,12 +80,8 @@ class ListItem < AbstractBlock
|
|
80
80
|
@text && (apply_subs @text, @subs)
|
81
81
|
end
|
82
82
|
|
83
|
-
# Public: Set the String text
|
84
|
-
|
85
|
-
# Returns the new String text assigned to this ListItem
|
86
|
-
def text= val
|
87
|
-
@text = val
|
88
|
-
end
|
83
|
+
# Public: Set the String text assigned to this ListItem
|
84
|
+
attr_writer :text
|
89
85
|
|
90
86
|
# Check whether this list item has simple content (no nested blocks aside from a single outline list).
|
91
87
|
# Primarily relevant for outline lists.
|
data/lib/asciidoctor/load.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Asciidoctor
|
2
3
|
class << self
|
3
4
|
# Public: Parse the AsciiDoc source input into a {Document}
|
@@ -53,7 +54,8 @@ module Asciidoctor
|
|
53
54
|
end
|
54
55
|
|
55
56
|
if ::File === input
|
56
|
-
|
57
|
+
# File#mtime on JRuby 9.1 for Windows doesn't honor TZ environment variable; see https://github.com/jruby/jruby/issues/6659
|
58
|
+
options[:input_mtime] = RUBY_ENGINE == 'jruby' ? (::Time.at input.mtime.to_i) : input.mtime
|
57
59
|
# NOTE defer setting infile and indir until we get a better sense of their purpose
|
58
60
|
# TODO cli checks if input path can be read and is file, but might want to add check to API too
|
59
61
|
attrs['docfile'] = input_path = ::File.absolute_path input.path
|
@@ -83,23 +85,23 @@ module Asciidoctor
|
|
83
85
|
|
84
86
|
timings.record :parse if timings
|
85
87
|
doc
|
86
|
-
rescue =>
|
88
|
+
rescue => e
|
87
89
|
begin
|
88
90
|
context = %(asciidoctor: FAILED: #{attrs['docfile'] || '<stdin>'}: Failed to load AsciiDoc document)
|
89
|
-
if
|
91
|
+
if e.respond_to? :exception
|
90
92
|
# The original message must be explicitly preserved when wrapping a Ruby exception
|
91
|
-
|
93
|
+
wrapped_e = e.exception %(#{context} - #{e.message})
|
92
94
|
# JRuby automatically sets backtrace; MRI did not until 2.6
|
93
|
-
|
95
|
+
wrapped_e.set_backtrace e.backtrace
|
94
96
|
else
|
95
97
|
# Likely a Java exception class
|
96
|
-
|
97
|
-
|
98
|
+
wrapped_e = e.class.new context, e
|
99
|
+
wrapped_e.stack_trace = e.stack_trace
|
98
100
|
end
|
99
101
|
rescue
|
100
|
-
|
102
|
+
wrapped_e = e
|
101
103
|
end
|
102
|
-
raise
|
104
|
+
raise wrapped_e
|
103
105
|
end
|
104
106
|
|
105
107
|
# Public: Parse the contents of the AsciiDoc source file into an Asciidoctor::Document
|
data/lib/asciidoctor/logging.rb
CHANGED
@@ -20,10 +20,10 @@ class Logger < ::Logger
|
|
20
20
|
end
|
21
21
|
|
22
22
|
class BasicFormatter < Formatter
|
23
|
-
|
23
|
+
SEVERITY_LABEL_SUBSTITUTES = { 'WARN' => 'WARNING', 'FATAL' => 'FAILED' }
|
24
24
|
|
25
25
|
def call severity, _, progname, msg
|
26
|
-
%(#{progname}: #{
|
26
|
+
%(#{progname}: #{SEVERITY_LABEL_SUBSTITUTES[severity] || severity}: #{::String === msg ? msg : msg.inspect}#{LF})
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -35,7 +35,7 @@ class Logger < ::Logger
|
|
35
35
|
end
|
36
36
|
|
37
37
|
class MemoryLogger < ::Logger
|
38
|
-
|
38
|
+
SEVERITY_SYMBOL_BY_VALUE = (Severity.constants false).map {|c| [(Severity.const_get c), c] }.to_h
|
39
39
|
|
40
40
|
attr_reader :messages
|
41
41
|
|
@@ -45,8 +45,8 @@ class MemoryLogger < ::Logger
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def add severity, message = nil, progname = nil
|
48
|
-
message
|
49
|
-
@messages << { severity:
|
48
|
+
message ||= block_given? ? yield : progname
|
49
|
+
@messages << { severity: SEVERITY_SYMBOL_BY_VALUE[severity || UNKNOWN], message: message }
|
50
50
|
true
|
51
51
|
end
|
52
52
|
|
@@ -59,7 +59,7 @@ class MemoryLogger < ::Logger
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def max_severity
|
62
|
-
empty? ? nil : @messages.map {|m| Severity.const_get m[:severity]
|
62
|
+
empty? ? nil : @messages.map {|m| Severity.const_get m[:severity] }.max
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
@@ -89,6 +89,7 @@ module LoggerManager
|
|
89
89
|
@logger ||= (@logger_class.new pipe)
|
90
90
|
end
|
91
91
|
|
92
|
+
# Returns the specified Logger
|
92
93
|
def logger= new_logger
|
93
94
|
@logger = new_logger || (@logger_class.new $stderr)
|
94
95
|
end
|
@@ -110,9 +111,10 @@ module Logging
|
|
110
111
|
# into - The Class that includes the {Logging} module
|
111
112
|
#
|
112
113
|
# Returns nothing
|
113
|
-
|
114
|
+
def self.included into
|
114
115
|
into.extend Logging
|
115
|
-
end
|
116
|
+
end
|
117
|
+
private_class_method :included # use separate declaration for Ruby 2.0.x
|
116
118
|
|
117
119
|
def logger
|
118
120
|
LoggerManager.logger
|