asciidoctor 2.0.13 → 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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +151 -30
  3. data/LICENSE +1 -1
  4. data/README-de.adoc +9 -12
  5. data/README-fr.adoc +9 -12
  6. data/README-jp.adoc +10 -13
  7. data/README-zh_CN.adoc +9 -12
  8. data/README.adoc +40 -19
  9. data/asciidoctor.gemspec +2 -9
  10. data/data/locale/attributes-fr.adoc +2 -2
  11. data/data/locale/attributes-th.adoc +23 -0
  12. data/data/locale/attributes-vi.adoc +23 -0
  13. data/data/stylesheets/asciidoctor-default.css +54 -53
  14. data/data/stylesheets/coderay-asciidoctor.css +9 -9
  15. data/lib/asciidoctor/abstract_block.rb +11 -9
  16. data/lib/asciidoctor/abstract_node.rb +9 -8
  17. data/lib/asciidoctor/attribute_list.rb +1 -1
  18. data/lib/asciidoctor/block.rb +6 -6
  19. data/lib/asciidoctor/cli/invoker.rb +1 -2
  20. data/lib/asciidoctor/cli/options.rb +25 -25
  21. data/lib/asciidoctor/convert.rb +1 -0
  22. data/lib/asciidoctor/converter/docbook5.rb +45 -26
  23. data/lib/asciidoctor/converter/html5.rb +130 -102
  24. data/lib/asciidoctor/converter/manpage.rb +69 -64
  25. data/lib/asciidoctor/converter/template.rb +12 -13
  26. data/lib/asciidoctor/converter.rb +6 -4
  27. data/lib/asciidoctor/core_ext/hash/merge.rb +1 -1
  28. data/lib/asciidoctor/document.rb +61 -57
  29. data/lib/asciidoctor/extensions.rb +20 -12
  30. data/lib/asciidoctor/list.rb +2 -6
  31. data/lib/asciidoctor/load.rb +11 -9
  32. data/lib/asciidoctor/logging.rb +10 -8
  33. data/lib/asciidoctor/parser.rb +177 -193
  34. data/lib/asciidoctor/path_resolver.rb +3 -3
  35. data/lib/asciidoctor/reader.rb +73 -72
  36. data/lib/asciidoctor/rx.rb +5 -4
  37. data/lib/asciidoctor/section.rb +7 -0
  38. data/lib/asciidoctor/substitutors.rb +121 -121
  39. data/lib/asciidoctor/syntax_highlighter/coderay.rb +2 -1
  40. data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +1 -1
  41. data/lib/asciidoctor/syntax_highlighter/pygments.rb +16 -7
  42. data/lib/asciidoctor/syntax_highlighter/rouge.rb +2 -1
  43. data/lib/asciidoctor/syntax_highlighter.rb +8 -11
  44. data/lib/asciidoctor/table.rb +18 -20
  45. data/lib/asciidoctor/timings.rb +3 -3
  46. data/lib/asciidoctor/version.rb +1 -1
  47. data/lib/asciidoctor.rb +10 -10
  48. data/man/asciidoctor.1 +26 -28
  49. data/man/asciidoctor.adoc +33 -27
  50. metadata +8 -62
@@ -40,13 +40,13 @@ class Converter::TemplateConverter < Converter::Base
40
40
  @caches = { scans: {}, templates: {} }
41
41
  end
42
42
 
43
- def self.caches
44
- @caches
45
- end
43
+ class << self
44
+ attr_reader :caches
46
45
 
47
- def self.clear_caches
48
- @caches[:scans].clear if @caches[:scans]
49
- @caches[:templates].clear if @caches[:templates]
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
- @templates[name] = if (template_cache = @caches[:templates])
137
+ if (template_cache = @caches[:templates])
138
138
  template_cache[template.file] = template
139
- else
140
- template
141
139
  end
142
- #create_handler name, template
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).select {|match| ::File.file? match }.each do |file|
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, { engine_class: ::Erubis::FastEruby }]
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
- private_class_method def self.included into
369
+ def self.included into
370
370
  into.send :include, BackendTraits
371
371
  into.extend Config
372
- end || :included
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 Converter, Logging
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 ? super({}) : (len > 1 ? args.inject(self) {|acc, arg| acc.merge arg } : (super args[0]))
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
@@ -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 compatiblity
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
- # NOTE we must dup or else all the assignments to the overrides clobbers the real attributes
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 furthur down if initialize_extensions is true
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
- attrs['attribute-undefined'] = Compliance.attribute_undefined
343
- attrs['attribute-missing'] = Compliance.attribute_missing
344
- attrs.update DEFAULT_ATTRIBUTES
345
- # TODO if lang attribute is set, @safe mode < SafeMode::SERVER, and !parent_doc,
346
- # load attributes from data/locale/attributes-<lang>.adoc
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 Python
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'] = %(#{backend_val})
401
+ attr_overrides['backend'] = backend_val.to_s
401
402
  end
402
403
 
403
404
  if (doctype_val = options[:doctype])
404
- attr_overrides['doctype'] = %(#{doctype_val})
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
- @attributes[name]
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
- @attributes[name] = @counters[name] = seed == seed.to_i.to_s ? seed.to_i : seed
571
+ next_val = @counters[name] = seed == seed.to_i.to_s ? seed.to_i : seed
571
572
  else
572
- @attributes[name] = @counters[name] = Helpers.nextval attr_seed ? attr_val : 0
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
- # NOTE short-circuit early since we're throwing away this table
618
- (@reftexts = {}).tap {|accum| @catalog[:refs].each {|id, ref| (xreftext = ref.xreftext) == text ? (break (resolved_id = id)) : (accum[xreftext] ||= id) } }
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 new [String] title assigned to the document header
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 file
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 = @outfilesuffix unless 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 != nil ? @header.title : nil).inspect}, blocks: #{@blocks.size}}>)
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'] if attrs.key? '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
- return @doctype = attrs['doctype'] = new_doctype
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
- else
144
- sect.numbered = true if opts.fetch :numbered, (book && (doc.attr? 'partnums'))
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 (opts[:positional_attributes] || [])
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 accomodate both concrete extension implementations and Procs.
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 additionnal docinfo to the document.
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
- # cooresponding BlockMacroProcessor or nil if a match is not found.
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
- # cooresponding InlineMacroProcessor or nil if a match is not found.
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
- extension = if block_given?
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
@@ -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.
@@ -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
- options[:input_mtime] = input.mtime
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 => ex
88
+ rescue => e
87
89
  begin
88
90
  context = %(asciidoctor: FAILED: #{attrs['docfile'] || '<stdin>'}: Failed to load AsciiDoc document)
89
- if ex.respond_to? :exception
91
+ if e.respond_to? :exception
90
92
  # The original message must be explicitly preserved when wrapping a Ruby exception
91
- wrapped_ex = ex.exception %(#{context} - #{ex.message})
93
+ wrapped_e = e.exception %(#{context} - #{e.message})
92
94
  # JRuby automatically sets backtrace; MRI did not until 2.6
93
- wrapped_ex.set_backtrace ex.backtrace
95
+ wrapped_e.set_backtrace e.backtrace
94
96
  else
95
97
  # Likely a Java exception class
96
- wrapped_ex = ex.class.new context, ex
97
- wrapped_ex.stack_trace = ex.stack_trace
98
+ wrapped_e = e.class.new context, e
99
+ wrapped_e.stack_trace = e.stack_trace
98
100
  end
99
101
  rescue
100
- wrapped_ex = ex
102
+ wrapped_e = e
101
103
  end
102
- raise wrapped_ex
104
+ raise wrapped_e
103
105
  end
104
106
 
105
107
  # Public: Parse the contents of the AsciiDoc source file into an Asciidoctor::Document
@@ -20,10 +20,10 @@ class Logger < ::Logger
20
20
  end
21
21
 
22
22
  class BasicFormatter < Formatter
23
- SEVERITY_LABELS = { 'WARN' => 'WARNING', 'FATAL' => 'FAILED' }
23
+ SEVERITY_LABEL_SUBSTITUTES = { 'WARN' => 'WARNING', 'FATAL' => 'FAILED' }
24
24
 
25
25
  def call severity, _, progname, msg
26
- %(#{progname}: #{SEVERITY_LABELS[severity] || severity}: #{::String === msg ? msg : msg.inspect}#{LF})
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
- SEVERITY_LABELS = {}.tap {|accum| (Severity.constants false).each {|c| accum[Severity.const_get c, false] = c } }
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 = block_given? ? yield : progname unless message
49
- @messages << { severity: SEVERITY_LABELS[severity || UNKNOWN], message: message }
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], false }.max
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
- private_class_method def self.included into
114
+ def self.included into
114
115
  into.extend Logging
115
- end || :included
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