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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +86 -11
  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 +33 -18
  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/block.rb +6 -6
  18. data/lib/asciidoctor/cli/invoker.rb +1 -2
  19. data/lib/asciidoctor/cli/options.rb +25 -25
  20. data/lib/asciidoctor/convert.rb +1 -0
  21. data/lib/asciidoctor/converter/docbook5.rb +20 -22
  22. data/lib/asciidoctor/converter/html5.rb +112 -94
  23. data/lib/asciidoctor/converter/manpage.rb +61 -52
  24. data/lib/asciidoctor/converter/template.rb +12 -13
  25. data/lib/asciidoctor/converter.rb +6 -4
  26. data/lib/asciidoctor/core_ext/hash/merge.rb +1 -1
  27. data/lib/asciidoctor/document.rb +39 -41
  28. data/lib/asciidoctor/extensions.rb +20 -12
  29. data/lib/asciidoctor/list.rb +2 -6
  30. data/lib/asciidoctor/load.rb +10 -9
  31. data/lib/asciidoctor/logging.rb +10 -8
  32. data/lib/asciidoctor/parser.rb +172 -189
  33. data/lib/asciidoctor/path_resolver.rb +3 -3
  34. data/lib/asciidoctor/reader.rb +71 -72
  35. data/lib/asciidoctor/rx.rb +3 -2
  36. data/lib/asciidoctor/section.rb +7 -0
  37. data/lib/asciidoctor/substitutors.rb +101 -103
  38. data/lib/asciidoctor/syntax_highlighter/coderay.rb +2 -1
  39. data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +1 -1
  40. data/lib/asciidoctor/syntax_highlighter/pygments.rb +14 -5
  41. data/lib/asciidoctor/syntax_highlighter/rouge.rb +2 -1
  42. data/lib/asciidoctor/syntax_highlighter.rb +8 -11
  43. data/lib/asciidoctor/table.rb +18 -20
  44. data/lib/asciidoctor/timings.rb +3 -3
  45. data/lib/asciidoctor/version.rb +1 -1
  46. data/lib/asciidoctor.rb +7 -7
  47. data/man/asciidoctor.1 +26 -28
  48. data/man/asciidoctor.adoc +33 -27
  49. metadata +8 -62
@@ -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
@@ -286,7 +286,6 @@ class Document < AbstractBlock
286
286
  footnotes: [],
287
287
  links: [],
288
288
  images: [],
289
- #indexterms: [],
290
289
  callouts: Callouts.new,
291
290
  includes: {},
292
291
  }
@@ -311,7 +310,7 @@ class Document < AbstractBlock
311
310
  end
312
311
  attr_overrides[key.downcase] = val
313
312
  end
314
- if (to_file = options[:to_file])
313
+ if ::String === (to_file = options[:to_file])
315
314
  attr_overrides['outfilesuffix'] = Helpers.extname to_file
316
315
  end
317
316
  # safely resolve the safe mode from const, int or string
@@ -329,7 +328,7 @@ class Document < AbstractBlock
329
328
  @timings = options.delete :timings
330
329
  @path_resolver = PathResolver.new
331
330
  initialize_extensions = (defined? ::Asciidoctor::Extensions) || (options.key? :extensions) ? ::Asciidoctor::Extensions : nil
332
- @extensions = nil # initialize furthur down if initialize_extensions is true
331
+ @extensions = nil # initialize further down if initialize_extensions is true
333
332
  options[:standalone] = options[:header_footer] if (options.key? :header_footer) && !(options.key? :standalone)
334
333
  end
335
334
 
@@ -360,9 +359,9 @@ class Document < AbstractBlock
360
359
  # sync embedded attribute with :standalone option value
361
360
  attr_overrides['embedded'] = ''
362
361
  if (attr_overrides.key? 'showtitle') && (attr_overrides.keys & %w(notitle showtitle))[-1] == 'showtitle'
363
- attr_overrides['notitle'] = { nil => '', false => '@', '@' => false}[attr_overrides['showtitle']]
362
+ attr_overrides['notitle'] = { nil => '', false => '@', '@' => false }[attr_overrides['showtitle']]
364
363
  elsif attr_overrides.key? 'notitle'
365
- attr_overrides['showtitle'] = { nil => '', false => '@', '@' => false}[attr_overrides['notitle']]
364
+ attr_overrides['showtitle'] = { nil => '', false => '@', '@' => false }[attr_overrides['notitle']]
366
365
  else
367
366
  attrs['notitle'] = ''
368
367
  end
@@ -399,11 +398,11 @@ class Document < AbstractBlock
399
398
 
400
399
  # allow common attributes backend and doctype to be set using options hash, coerce values to string
401
400
  if (backend_val = options[:backend])
402
- attr_overrides['backend'] = %(#{backend_val})
401
+ attr_overrides['backend'] = backend_val.to_s
403
402
  end
404
403
 
405
404
  if (doctype_val = options[:doctype])
406
- attr_overrides['doctype'] = %(#{doctype_val})
405
+ attr_overrides['doctype'] = doctype_val.to_s
407
406
  end
408
407
 
409
408
  if @safe >= SafeMode::SERVER
@@ -566,9 +565,7 @@ class Document < AbstractBlock
566
565
  # returns the next number in the sequence for the specified counter
567
566
  def counter name, seed = nil
568
567
  return @parent_document.counter name, seed if @parent_document
569
- if (locked = attribute_locked? name) && (curr_val = @counters[name])
570
- next_val = @counters[name] = Helpers.nextval curr_val
571
- elsif !(curr_val = @attributes[name]).nil_or_empty?
568
+ if ((locked = attribute_locked? name) && (curr_val = @counters[name])) || !(curr_val = @attributes[name]).nil_or_empty?
572
569
  next_val = @counters[name] = Helpers.nextval curr_val
573
570
  elsif seed
574
571
  next_val = @counters[name] = seed == seed.to_i.to_s ? seed.to_i : seed
@@ -618,15 +615,29 @@ class Document < AbstractBlock
618
615
  # @reftexts is set eagerly to prevent nested lazy init
619
616
  (@reftexts = {}).tap {|accum| @catalog[:refs].each {|id, ref| accum[ref.xreftext] ||= id } }[text]
620
617
  else
621
- # @reftexts is set eagerly to prevent nested lazy init
622
618
  resolved_id = nil
623
- # NOTE short-circuit early since we're throwing away this table
624
- (@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
625
629
  @reftexts = nil
626
630
  resolved_id
627
631
  end
628
632
  end
629
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
+
630
641
  def footnotes?
631
642
  @catalog[:footnotes].empty? ? false : true
632
643
  end
@@ -679,7 +690,7 @@ class Document < AbstractBlock
679
690
  #
680
691
  # title - the String title to assign as the title of the document header
681
692
  #
682
- # Returns the new [String] title assigned to the document header
693
+ # Returns the specified [String] title
683
694
  def title= title
684
695
  unless (sect = @header)
685
696
  (sect = (@header = Section.new self, 0)).sectname = 'header'
@@ -961,8 +972,14 @@ class Document < AbstractBlock
961
972
 
962
973
  # Public: Write the output to the specified file
963
974
  #
964
- # If the converter responds to :write, delegate the work of writing the file
965
- # 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.
966
983
  #
967
984
  # Returns nothing
968
985
  def write output, target
@@ -988,25 +1005,6 @@ class Document < AbstractBlock
988
1005
  nil
989
1006
  end
990
1007
 
991
- =begin
992
- def convert_to target, opts = {}
993
- start = ::Time.now.to_f if (monitor = opts[:monitor])
994
- output = (r = converter opts).convert
995
- monitor[:convert] = ::Time.now.to_f - start if monitor
996
-
997
- unless target.respond_to? :write
998
- @attributes['outfile'] = target = ::File.expand_path target
999
- @attributes['outdir'] = ::File.dirname target
1000
- end
1001
-
1002
- start = ::Time.now.to_f if monitor
1003
- r.write output, target
1004
- monitor[:write] = ::Time.now.to_f - start if monitor
1005
-
1006
- output
1007
- end
1008
- =end
1009
-
1010
1008
  def content
1011
1009
  # NOTE per AsciiDoc-spec, remove the title before converting the body
1012
1010
  @attributes.delete('title')
@@ -1028,7 +1026,7 @@ class Document < AbstractBlock
1028
1026
  def docinfo location = :head, suffix = nil
1029
1027
  if safe < SafeMode::SECURE
1030
1028
  qualifier = %(-#{location}) unless location == :head
1031
- suffix = @outfilesuffix unless suffix
1029
+ suffix ||= @outfilesuffix
1032
1030
 
1033
1031
  if (docinfo = @attributes['docinfo']).nil_or_empty?
1034
1032
  if @attributes.key? 'docinfo2'
@@ -1085,7 +1083,7 @@ class Document < AbstractBlock
1085
1083
  end
1086
1084
 
1087
1085
  def to_s
1088
- %(#<#{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}}>)
1089
1087
  end
1090
1088
 
1091
1089
  private
@@ -1214,8 +1212,8 @@ class Document < AbstractBlock
1214
1212
  end
1215
1213
  end
1216
1214
 
1217
- if (@compat_mode = attrs.key? 'compat-mode')
1218
- 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']
1219
1217
  end
1220
1218
 
1221
1219
  unless @parent_document
@@ -1388,7 +1386,7 @@ class Document < AbstractBlock
1388
1386
  attrs[%(basebackend-#{current_basebackend}-doctype-#{new_doctype})] = '' if current_basebackend
1389
1387
  end
1390
1388
  attrs[%(doctype-#{new_doctype})] = ''
1391
- return @doctype = attrs['doctype'] = new_doctype
1389
+ @doctype = attrs['doctype'] = new_doctype
1392
1390
  end
1393
1391
  end
1394
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,7 @@ module Asciidoctor
53
54
  end
54
55
 
55
56
  if ::File === input
56
- # File#mtime on JRuby for Windows doesn't honor TZ environment variable; see https://github.com/jruby/jruby/issues/6659
57
+ # File#mtime on JRuby 9.1 for Windows doesn't honor TZ environment variable; see https://github.com/jruby/jruby/issues/6659
57
58
  options[:input_mtime] = RUBY_ENGINE == 'jruby' ? (::Time.at input.mtime.to_i) : input.mtime
58
59
  # NOTE defer setting infile and indir until we get a better sense of their purpose
59
60
  # TODO cli checks if input path can be read and is file, but might want to add check to API too
@@ -84,23 +85,23 @@ module Asciidoctor
84
85
 
85
86
  timings.record :parse if timings
86
87
  doc
87
- rescue => ex
88
+ rescue => e
88
89
  begin
89
90
  context = %(asciidoctor: FAILED: #{attrs['docfile'] || '<stdin>'}: Failed to load AsciiDoc document)
90
- if ex.respond_to? :exception
91
+ if e.respond_to? :exception
91
92
  # The original message must be explicitly preserved when wrapping a Ruby exception
92
- wrapped_ex = ex.exception %(#{context} - #{ex.message})
93
+ wrapped_e = e.exception %(#{context} - #{e.message})
93
94
  # JRuby automatically sets backtrace; MRI did not until 2.6
94
- wrapped_ex.set_backtrace ex.backtrace
95
+ wrapped_e.set_backtrace e.backtrace
95
96
  else
96
97
  # Likely a Java exception class
97
- wrapped_ex = ex.class.new context, ex
98
- wrapped_ex.stack_trace = ex.stack_trace
98
+ wrapped_e = e.class.new context, e
99
+ wrapped_e.stack_trace = e.stack_trace
99
100
  end
100
101
  rescue
101
- wrapped_ex = ex
102
+ wrapped_e = e
102
103
  end
103
- raise wrapped_ex
104
+ raise wrapped_e
104
105
  end
105
106
 
106
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