asciidoctor 1.5.1 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of asciidoctor might be problematic. Click here for more details.

Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +85 -0
  3. data/README.adoc +79 -6
  4. data/Rakefile +22 -1
  5. data/benchmark/benchmark.rb +3 -1
  6. data/compat/asciidoc.conf +2 -2
  7. data/data/stylesheets/asciidoctor-default.css +3 -3
  8. data/features/step_definitions.rb +12 -1
  9. data/lib/asciidoctor.rb +74 -42
  10. data/lib/asciidoctor/abstract_block.rb +5 -1
  11. data/lib/asciidoctor/abstract_node.rb +40 -23
  12. data/lib/asciidoctor/attribute_list.rb +14 -5
  13. data/lib/asciidoctor/block.rb +45 -12
  14. data/lib/asciidoctor/callouts.rb +1 -0
  15. data/lib/asciidoctor/cli/invoker.rb +6 -2
  16. data/lib/asciidoctor/cli/options.rb +23 -9
  17. data/lib/asciidoctor/converter.rb +9 -19
  18. data/lib/asciidoctor/converter/base.rb +11 -14
  19. data/lib/asciidoctor/converter/composite.rb +8 -19
  20. data/lib/asciidoctor/converter/docbook45.rb +1 -0
  21. data/lib/asciidoctor/converter/docbook5.rb +24 -2
  22. data/lib/asciidoctor/converter/factory.rb +1 -0
  23. data/lib/asciidoctor/converter/html5.rb +61 -25
  24. data/lib/asciidoctor/converter/template.rb +19 -26
  25. data/lib/asciidoctor/document.rb +73 -45
  26. data/lib/asciidoctor/extensions.rb +121 -9
  27. data/lib/asciidoctor/helpers.rb +1 -0
  28. data/lib/asciidoctor/inline.rb +1 -0
  29. data/lib/asciidoctor/list.rb +1 -0
  30. data/lib/asciidoctor/opal_ext.rb +22 -0
  31. data/lib/asciidoctor/opal_ext/file.rb +26 -13
  32. data/lib/asciidoctor/parser.rb +15 -18
  33. data/lib/asciidoctor/path_resolver.rb +18 -0
  34. data/lib/asciidoctor/reader.rb +8 -9
  35. data/lib/asciidoctor/section.rb +5 -8
  36. data/lib/asciidoctor/stylesheets.rb +1 -0
  37. data/lib/asciidoctor/substitutors.rb +18 -18
  38. data/lib/asciidoctor/table.rb +2 -1
  39. data/lib/asciidoctor/timings.rb +1 -0
  40. data/lib/asciidoctor/version.rb +1 -1
  41. data/man/asciidoctor.1 +10 -11
  42. data/man/asciidoctor.adoc +80 -99
  43. data/test/attributes_test.rb +42 -0
  44. data/test/blocks_test.rb +19 -7
  45. data/test/document_test.rb +114 -0
  46. data/test/extensions_test.rb +100 -0
  47. data/test/fixtures/custom-docinfodir/basic-docinfo.html +1 -0
  48. data/test/fixtures/custom-docinfodir/docinfo.html +1 -0
  49. data/test/fixtures/hello-asciidoctor.pdf +0 -0
  50. data/test/invoker_test.rb +4 -3
  51. data/test/lists_test.rb +31 -5
  52. data/test/options_test.rb +1 -1
  53. data/test/paths_test.rb +21 -0
  54. data/test/preamble_test.rb +33 -0
  55. data/test/reader_test.rb +13 -0
  56. data/test/sections_test.rb +22 -0
  57. data/test/substitutions_test.rb +49 -0
  58. data/test/tables_test.rb +76 -0
  59. data/test/test_helper.rb +4 -2
  60. metadata +7 -5
  61. data/lib/asciidoctor/debug.rb +0 -25
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Asciidoctor
2
3
  class AbstractBlock < AbstractNode
3
4
  # Public: The types of content that this block can accomodate
@@ -167,12 +168,15 @@ class AbstractBlock < AbstractNode
167
168
  # # => 2
168
169
  #
169
170
  # Returns nothing.
170
- def <<(block)
171
+ def << block
171
172
  # parent assignment pending refactor
172
173
  #block.parent = self
173
174
  @blocks << block
174
175
  end
175
176
 
177
+ # NOTE append alias required for adapting to a Java API
178
+ alias :append :<<
179
+
176
180
  # Public: Get the Array of child Section objects
177
181
  #
178
182
  # Only applies to Document and Section instances
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Asciidoctor
2
3
  # Public: An abstract base class that provides state and methods for managing a
3
4
  # node of AsciiDoc content. The state and methods on this class are comment to
@@ -32,6 +33,9 @@ class AbstractNode
32
33
  if parent
33
34
  @parent = parent
34
35
  @document = parent.document
36
+ else
37
+ @parent = nil
38
+ @document = nil
35
39
  end
36
40
  end
37
41
  @context = context
@@ -56,14 +60,18 @@ class AbstractNode
56
60
  #
57
61
  # Returns [Boolean]
58
62
  def inline?
63
+ # :nocov:
59
64
  raise ::NotImplementedError
65
+ # :nocov:
60
66
  end
61
67
 
62
68
  # Public: Returns whether this {AbstractNode} is an instance of {Block}
63
69
  #
64
70
  # Returns [Boolean]
65
71
  def block?
72
+ # :nocov:
66
73
  raise ::NotImplementedError
74
+ # :nocov:
67
75
  end
68
76
 
69
77
  # Public: Get the value of the specified attribute
@@ -269,11 +277,7 @@ class AbstractNode
269
277
  #
270
278
  # Returns A String reference for the target media
271
279
  def media_uri(target, asset_dir_key = 'imagesdir')
272
- if is_uri? target
273
- target
274
- else
275
- normalize_web_path target, (asset_dir_key ? @document.attr(asset_dir_key) : nil)
276
- end
280
+ normalize_web_path target, (asset_dir_key ? @document.attr(asset_dir_key) : nil)
277
281
  end
278
282
 
279
283
  # Public: Construct a URI reference or data URI to the target image.
@@ -298,9 +302,9 @@ class AbstractNode
298
302
  def image_uri(target_image, asset_dir_key = 'imagesdir')
299
303
  if (doc = @document).safe < SafeMode::SECURE && doc.attr?('data-uri')
300
304
  if is_uri?(target_image) ||
301
- (asset_dir_key && (images_base = doc.attr(asset_dir_key)) &&
302
- is_uri?(images_base) && (target_image = normalize_web_path target_image, images_base))
303
- if doc.attr? 'allow-uri-read'
305
+ (asset_dir_key && (images_base = doc.attr(asset_dir_key)) && is_uri?(images_base) &&
306
+ (target_image = normalize_web_path(target_image, images_base, false)))
307
+ if doc.attr?('allow-uri-read')
304
308
  generate_data_uri_from_uri target_image, doc.attr?('cache-uri')
305
309
  else
306
310
  target_image
@@ -308,8 +312,6 @@ class AbstractNode
308
312
  else
309
313
  generate_data_uri target_image, asset_dir_key
310
314
  end
311
- elsif is_uri? target_image
312
- target_image
313
315
  else
314
316
  normalize_web_path target_image, (asset_dir_key ? doc.attr(asset_dir_key) : nil)
315
317
  end
@@ -397,18 +399,27 @@ class AbstractNode
397
399
  # This method assumes that the path is safe to read. It checks
398
400
  # that the file is readable before attempting to read it.
399
401
  #
400
- # path - the String path from which to read the contents
401
- # warn_on_failure - a Boolean that controls whether a warning is issued if
402
- # the file cannot be read
402
+ # path - the String path from which to read the contents
403
+ # opts - a Hash of options to control processing (default: {})
404
+ # * :warn_on_failure a Boolean that controls whether a warning
405
+ # is issued if the file cannot be read (default: false)
406
+ # * :normalize a Boolean that controls whether the lines
407
+ # are normalized and coerced to UTF-8 (default: false)
403
408
  #
404
409
  # Returns the [String] content of the file at the specified path, or nil
405
410
  # if the file does not exist.
406
- def read_asset(path, warn_on_failure = false)
411
+ def read_asset(path, opts = {})
412
+ # remap opts for backwards compatibility
413
+ opts = { :warn_on_failure => (opts != false) } unless ::Hash === opts
407
414
  if ::File.readable? path
408
- # QUESTION should we use strip or rstrip instead of chomp here?
409
- ::File.read(path).chomp
415
+ if opts[:normalize]
416
+ # QUESTION should we strip content?
417
+ Helpers.normalize_lines_from_string(::IO.read(path)) * EOL
418
+ else
419
+ ::IO.read(path)
420
+ end
410
421
  else
411
- warn "asciidoctor: WARNING: file does not exist or cannot be read: #{path}" if warn_on_failure
422
+ warn %(asciidoctor: WARNING: file does not exist or cannot be read: #{path}) if opts[:warn_on_failure]
412
423
  nil
413
424
  end
414
425
  end
@@ -417,12 +428,17 @@ class AbstractNode
417
428
  #
418
429
  # See {PathResolver#web_path} for details.
419
430
  #
420
- # target - the String target path
421
- # start - the String start (i.e, parent) path (optional, default: nil)
431
+ # target - the String target path
432
+ # start - the String start (i.e, parent) path (optional, default: nil)
433
+ # preserve_uri_target - a Boolean indicating whether target should be preserved if contains a URI (default: true)
422
434
  #
423
435
  # Returns the resolved [String] path
424
- def normalize_web_path(target, start = nil)
425
- (@path_resolver ||= PathResolver.new).web_path(target, start)
436
+ def normalize_web_path(target, start = nil, preserve_uri_target = true)
437
+ if preserve_uri_target && is_uri?(target)
438
+ target
439
+ else
440
+ (@path_resolver ||= PathResolver.new).web_path target, start
441
+ end
426
442
  end
427
443
 
428
444
  # Public: Resolve and normalize a secure path from the target and start paths
@@ -451,9 +467,10 @@ class AbstractNode
451
467
  # parent references resolved and self references removed. If a jail is provided,
452
468
  # this path will be guaranteed to be contained within the jail.
453
469
  def normalize_system_path target, start = nil, jail = nil, opts = {}
470
+ path_resolver = (@path_resolver ||= PathResolver.new)
454
471
  if (doc = @document).safe < SafeMode::SAFE
455
472
  if start
456
- start = ::File.join doc.base_dir, start unless (@path_resolver ||= PathResolver.new).is_root? start
473
+ start = ::File.join doc.base_dir, start unless path_resolver.is_root? start
457
474
  else
458
475
  start = doc.base_dir
459
476
  end
@@ -461,7 +478,7 @@ class AbstractNode
461
478
  start = doc.base_dir unless start
462
479
  jail = doc.base_dir unless jail
463
480
  end
464
- (@path_resolver ||= PathResolver.new).system_path target, start, jail, opts
481
+ path_resolver.system_path target, start, jail, opts
465
482
  end
466
483
 
467
484
  # Public: Normalize the asset file or directory to a concrete and rinsed path
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Asciidoctor
2
3
  # Public: Handles parsing AsciiDoc attribute lists into a Hash of key/value
3
4
  # pairs. By default, attributes must each be separated by a comma and quotes
@@ -22,11 +23,19 @@ module Asciidoctor
22
23
  #
23
24
  class AttributeList
24
25
 
26
+ # FIXME Opal not inheriting constants from parent scope
27
+ # NOTE can't use ::RUBY_ENGINE_OPAL here either
28
+ if ::RUBY_ENGINE == 'opal'
29
+ CG_BLANK = '[ \\t]'
30
+ CC_WORD = 'a-zA-Z0-9_'
31
+ CG_WORD = '[a-zA-Z0-9_]'
32
+ end
33
+
25
34
  # Public: Regular expressions for detecting the boundary of a value
26
35
  BoundaryRxs = {
27
36
  '"' => /.*?[^\\](?=")/,
28
37
  '\'' => /.*?[^\\](?=')/,
29
- ',' => /.*?(?=[ \t]*(,|$))/
38
+ ',' => /.*?(?=#{CG_BLANK}*(,|$))/
30
39
  }
31
40
 
32
41
  # Public: Regular expressions for unescaping quoted characters
@@ -35,16 +44,16 @@ class AttributeList
35
44
  '\'' => /\\'/
36
45
  }
37
46
 
38
- # Public: A regular expression for an attribute name
47
+ # Public: A regular expression for an attribute name (approx. name token from XML)
39
48
  # TODO named attributes cannot contain dash characters
40
- NameRx = /[A-Za-z:_][A-Za-z:_\-.]*/
49
+ NameRx = /#{CG_WORD}[#{CC_WORD}\-.]*/
41
50
 
42
- BlankRx = /[ \t]+/
51
+ BlankRx = /#{CG_BLANK}+/
43
52
 
44
53
  # Public: Regular expressions for skipping blanks and delimiters
45
54
  SkipRxs = {
46
55
  :blank => BlankRx,
47
- ',' => /[ \t]*(,|$)/
56
+ ',' => /#{CG_BLANK}*(,|$)/
48
57
  }
49
58
 
50
59
  def initialize source, block = nil, delimiter = ','
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Asciidoctor
2
3
  # Public: Methods for managing blocks of Asciidoc content in a section.
3
4
  #
@@ -8,7 +9,7 @@ module Asciidoctor
8
9
  # => "<em>This</em> is a &lt;test&gt;"
9
10
  class Block < AbstractBlock
10
11
 
11
- DEFAULT_CONTENT_MODEL = ::Hash.new(:simple).merge({
12
+ DEFAULT_CONTENT_MODEL = {
12
13
  # TODO should probably fill in all known blocks
13
14
  :audio => :empty,
14
15
  :image => :empty,
@@ -20,7 +21,8 @@ class Block < AbstractBlock
20
21
  :pass => :raw,
21
22
  :thematic_break => :empty,
22
23
  :video => :empty
23
- })
24
+ }
25
+ DEFAULT_CONTENT_MODEL.default = :simple
24
26
 
25
27
  # Public: Create alias for context to be consistent w/ AsciiDoc
26
28
  alias :blockname :context
@@ -37,25 +39,56 @@ class Block < AbstractBlock
37
39
  # how the lines should be processed (:simple, :verbatim, :raw, :empty). (default: :simple)
38
40
  # * :attributes a Hash of attributes (key/value pairs) to assign to this Block. (default: {})
39
41
  # * :source a String or Array of raw source for this Block. (default: nil)
42
+ #
43
+ # IMPORTANT: If you don't specify the `:subs` option, you must explicitly call
44
+ # the `lock_in_subs` method to resolve and assign the substitutions to this
45
+ # block (which are resolved from the `subs` attribute, if specified, or the
46
+ # default substitutions based on this block's context). If you want to use the
47
+ # default subs for a block, pass the option `:subs => :default`. You can
48
+ # override the default subs using the `:default_subs` option.
40
49
  #--
41
50
  # QUESTION should we store source_data as lines for blocks that have compound content models?
42
51
  def initialize parent, context, opts = {}
43
52
  super
44
53
  @content_model = opts[:content_model] || DEFAULT_CONTENT_MODEL[context]
45
- if opts.has_key? :subs
46
- # FIXME this is a bit funky
47
- # we have to be defensive to avoid lock_in_subs wiping out the override
48
- if !(subs = opts[:subs]) || (subs.is_a? ::Array)
49
- @subs = subs || []
50
- @default_subs = @subs.dup
51
- @attributes.delete('subs')
54
+ if opts.key? :subs
55
+ # FIXME feels funky; we have to be defensive to get lock_in_subs to honor override
56
+ # FIXME does not resolve substitution groups inside Array (e.g., [:normal])
57
+ if (subs = opts[:subs])
58
+ # e.g., :subs => :defult
59
+ # subs attribute is honored; falls back to opts[:default_subs], then built-in defaults based on context
60
+ if subs == :default
61
+ @default_subs = opts[:default_subs]
62
+ # e.g., :subs => [:quotes]
63
+ # subs attribute is not honored
64
+ elsif ::Array === subs
65
+ @default_subs = subs.dup
66
+ @attributes.delete 'subs'
67
+ # e.g., :subs => :normal or :subs => 'normal'
68
+ # subs attribute is not honored
69
+ else
70
+ @default_subs = nil
71
+ # interpolation is the fastest way to dup subs as a string
72
+ @attributes['subs'] = %(#{subs})
73
+ end
74
+ # resolve the subs eagerly only if subs option is specified
75
+ lock_in_subs
76
+ # e.g., :subs => nil
52
77
  else
53
- @attributes['subs'] = %(#{subs})
78
+ @subs = []
79
+ # prevent subs from being resolved
80
+ @default_subs = []
81
+ @attributes.delete 'subs'
54
82
  end
83
+ # defer subs resolution; subs attribute is honored
84
+ else
85
+ @subs = []
86
+ # QUESTION should we honor :default_subs option (i.e., @default_subs = opts[:default_subs])?
87
+ @default_subs = nil
55
88
  end
56
- if !(raw_source = opts[:source])
89
+ if (raw_source = opts[:source]).nil_or_empty?
57
90
  @lines = []
58
- elsif raw_source.is_a? ::String
91
+ elsif ::String === raw_source
59
92
  @lines = Helpers.normalize_lines_from_string raw_source
60
93
  else
61
94
  @lines = raw_source.dup
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Asciidoctor
2
3
  # Public: Maintains a catalog of callouts and their associations.
3
4
  class Callouts
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Asciidoctor
2
3
  module Cli
3
4
  # Public Invocation class for starting Asciidoctor via CLI
@@ -104,8 +105,11 @@ module Asciidoctor
104
105
  raise e
105
106
  else
106
107
  err = (@err || $stderr)
107
- err.print %(#{e.class}: ) if ::RuntimeError === e
108
- err.puts e.message
108
+ if ::RuntimeError === e
109
+ err.puts %(#{e.message} (#{e.class}))
110
+ else
111
+ err.puts e.message
112
+ end
109
113
  err.puts ' Use --trace for backtrace'
110
114
  end
111
115
  end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Asciidoctor
2
3
  module Cli
3
4
 
@@ -49,7 +50,7 @@ Example: asciidoctor -b html5 source.asciidoc
49
50
  'document type to use when converting document: [article, book, manpage, inline] (default: article)') do |doc_type|
50
51
  self[:attributes]['doctype'] = doc_type
51
52
  end
52
- opts.on('-o', '--out-file FILE', 'output file (default: based on input file path); use - to output to STDOUT') do |output_file|
53
+ opts.on('-o', '--out-file FILE', 'output file (default: based on path of input file); use - to output to STDOUT') do |output_file|
53
54
  self[:output_file] = output_file
54
55
  end
55
56
  opts.on('--safe',
@@ -134,9 +135,7 @@ Example: asciidoctor -b html5 source.asciidoc
134
135
  end
135
136
 
136
137
  opts.on_tail('-V', '--version', 'display the version and runtime environment (or -v if no other flags or arguments)') do
137
- $stdout.puts %(Asciidoctor #{::Asciidoctor::VERSION} [http://asciidoctor.org])
138
- $stdout.puts %(Runtime Environment (#{RUBY_DESCRIPTION}))
139
- return 0
138
+ return print_version $stdout
140
139
  end
141
140
 
142
141
  end
@@ -146,9 +145,7 @@ Example: asciidoctor -b html5 source.asciidoc
146
145
 
147
146
  if args.empty?
148
147
  if self[:verbose] == 2
149
- $stdout.puts %(Asciidoctor #{::Asciidoctor::VERSION} [http://asciidoctor.org])
150
- $stdout.puts %(Runtime Environment (#{RUBY_DESCRIPTION}))
151
- return 0
148
+ return print_version $stdout
152
149
  else
153
150
  $stderr.puts opts_parser
154
151
  return 1
@@ -183,8 +180,12 @@ Example: asciidoctor -b html5 source.asciidoc
183
180
  end
184
181
 
185
182
  infiles.each do |file|
186
- unless file == '-' || (::File.readable? file)
187
- $stderr.puts %(asciidoctor: FAILED: input file #{file} missing or cannot be read)
183
+ unless file == '-' || (::File.file? file)
184
+ if ::File.readable? file
185
+ $stderr.puts %(asciidoctor: FAILED: input path #{file} is a #{(::File.stat file).ftype}, not a file)
186
+ else
187
+ $stderr.puts %(asciidoctor: FAILED: input file #{file} missing or cannot be read)
188
+ end
188
189
  return 1
189
190
  end
190
191
  end
@@ -238,6 +239,19 @@ Example: asciidoctor -b html5 source.asciidoc
238
239
  $stdout.puts opts_parser
239
240
  return 1
240
241
  end
242
+
243
+ def print_version os = $stdout
244
+ os.puts %(Asciidoctor #{::Asciidoctor::VERSION} [http://asciidoctor.org])
245
+ if RUBY_VERSION >= '1.9.3'
246
+ encoding_info = {'lc' => 'locale', 'fs' => 'filesystem', 'in' => 'internal', 'ex' => 'external'}.map do |k,v|
247
+ %(#{k}:#{Encoding.find(v) || '-'})
248
+ end
249
+ os.puts %(Runtime Environment (#{RUBY_DESCRIPTION}) (#{encoding_info * ' '}))
250
+ else
251
+ os.puts %(Runtime Environment (#{RUBY_DESCRIPTION}))
252
+ end
253
+ 0
254
+ end
241
255
  end
242
256
  end
243
257
  end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Asciidoctor
2
3
  # A base module for defining converters that can be used to convert {AbstractNode}
3
4
  # objects in a parsed AsciiDoc document to a backend format such as HTML or
@@ -160,9 +161,9 @@ module Asciidoctor
160
161
  end
161
162
  =end
162
163
 
163
- # Public: Converts an {AbstractNode} using the specified transform. If a
164
- # transform is not specified, implementations typically derive one from the
165
- # {AbstractNode#node_name} property.
164
+ # Public: Converts an {AbstractNode} using the specified transform along
165
+ # with additional options. If a transform is not specified, implementations
166
+ # typically derive one from the {AbstractNode#node_name} property.
166
167
  #
167
168
  # Implementations are free to decide how to carry out the conversion. In
168
169
  # the case of the built-in converters, the tranform value is used to
@@ -174,27 +175,16 @@ module Asciidoctor
174
175
  # should be applied to this node. If a transform is not specified,
175
176
  # the transform is typically derived from the value of the
176
177
  # node's node_name property. (optional, default: nil)
178
+ # opts - An optional Hash of options that provide additional hints about
179
+ # how to convert the node. (optional, default: {})
177
180
  #
178
181
  # Returns the [String] result
179
- def convert node, transform = nil
182
+ def convert node, transform = nil, opts = {}
180
183
  raise ::NotImplementedError
181
184
  end
182
185
 
183
- # Public: Converts an {AbstractNode} using the specified transform along
184
- # with additional options. Delegates to {#convert} without options by default.
185
- #
186
- # node - The concrete instance of AbstractNode to convert
187
- # transform - An optional String transform that hints at which transformation
188
- # should be applied to this node. If a transform is not specified,
189
- # the transform is typically derived from the value of the
190
- # node's node_name property. (optional, default: nil)
191
- # opts - An optional Hash of options that provide additional hints about
192
- # how to convert the node.
193
- #
194
- # Returns the [String] result
195
- def convert_with_options node, transform = nil, opts = {}
196
- convert node, transform
197
- end
186
+ # Alias for backward compatibility.
187
+ alias :convert_with_options :convert
198
188
  end
199
189
 
200
190
  # A module that can be used to mix the {#write} method into a {Converter}
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Asciidoctor
2
3
  module Converter; end # required for Opal
3
4
 
@@ -16,25 +17,21 @@ module Asciidoctor
16
17
  def initialize backend, opts = {}
17
18
  end
18
19
 
19
- # Public: Converts the specified {AbstractNode} using the specified transform.
20
+ # Public: Converts the specified {AbstractNode} using the specified
21
+ # transform and optionally additional options (when not empty).
20
22
  #
21
- # See {Converter#convert} for more details.
23
+ # CAUTION: Method that handles the specified transform *may not* accept the
24
+ # second argument with additional options, in which case an {ArgumentError}
25
+ # is raised if the given +opts+ Hash is not nil. The additional options are
26
+ # used in template-based backends to access convert helper methods such as
27
+ # outline.
22
28
  #
23
- # Returns the [String] result of conversion
24
- def convert node, transform = nil
25
- transform ||= node.node_name
26
- send transform, node
27
- end
28
-
29
- # Public: Converts the specified {AbstractNode} using the specified transform
30
- # with additional options.
31
- #
32
- # See {Converter#convert_with_options} for more details.
29
+ # See {Converter#convert} for more details.
33
30
  #
34
31
  # Returns the [String] result of conversion
35
- def convert_with_options node, transform = nil, opts = {}
32
+ def convert node, transform = nil, opts = {}
36
33
  transform ||= node.node_name
37
- send transform, node, opts
34
+ opts.empty? ? (send transform, node) : (send transform, node, opts)
38
35
  end
39
36
 
40
37
  alias :handles? :respond_to?