asciidoctor 1.5.8 → 2.0.0.rc.1

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 (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +162 -17
  3. data/LICENSE +1 -1
  4. data/README-de.adoc +12 -13
  5. data/README-fr.adoc +11 -12
  6. data/README-jp.adoc +11 -12
  7. data/README-zh_CN.adoc +12 -13
  8. data/README.adoc +6 -7
  9. data/asciidoctor.gemspec +19 -24
  10. data/bin/asciidoctor +5 -4
  11. data/data/reference/syntax.adoc +283 -0
  12. data/data/stylesheets/asciidoctor-default.css +56 -52
  13. data/data/stylesheets/coderay-asciidoctor.css +7 -9
  14. data/lib/asciidoctor.rb +171 -232
  15. data/lib/asciidoctor/abstract_block.rb +96 -105
  16. data/lib/asciidoctor/abstract_node.rb +118 -139
  17. data/lib/asciidoctor/attribute_list.rb +10 -14
  18. data/lib/asciidoctor/block.rb +20 -19
  19. data/lib/asciidoctor/callouts.rb +4 -2
  20. data/lib/asciidoctor/cli.rb +3 -2
  21. data/lib/asciidoctor/cli/invoker.rb +14 -21
  22. data/lib/asciidoctor/cli/options.rb +64 -54
  23. data/lib/asciidoctor/converter.rb +357 -185
  24. data/lib/asciidoctor/converter/composite.rb +40 -48
  25. data/lib/asciidoctor/converter/docbook5.rb +604 -640
  26. data/lib/asciidoctor/converter/html5.rb +949 -963
  27. data/lib/asciidoctor/converter/manpage.rb +569 -548
  28. data/lib/asciidoctor/converter/template.rb +231 -272
  29. data/lib/asciidoctor/core_ext.rb +5 -18
  30. data/lib/asciidoctor/core_ext/float/truncate.rb +19 -0
  31. data/lib/asciidoctor/core_ext/match_data/names.rb +7 -0
  32. data/lib/asciidoctor/core_ext/nil_or_empty.rb +1 -0
  33. data/lib/asciidoctor/core_ext/regexp/is_match.rb +4 -2
  34. data/lib/asciidoctor/document.rb +399 -377
  35. data/lib/asciidoctor/extensions.rb +72 -140
  36. data/lib/asciidoctor/helpers.rb +122 -83
  37. data/lib/asciidoctor/inline.rb +5 -1
  38. data/lib/asciidoctor/list.rb +13 -11
  39. data/lib/asciidoctor/logging.rb +17 -16
  40. data/lib/asciidoctor/parser.rb +390 -423
  41. data/lib/asciidoctor/path_resolver.rb +10 -5
  42. data/lib/asciidoctor/reader.rb +286 -263
  43. data/lib/asciidoctor/rouge_ext.rb +39 -0
  44. data/lib/asciidoctor/section.rb +9 -8
  45. data/lib/asciidoctor/stylesheets.rb +19 -37
  46. data/lib/asciidoctor/substitutors.rb +364 -509
  47. data/lib/asciidoctor/syntax_highlighter.rb +238 -0
  48. data/lib/asciidoctor/syntax_highlighter/coderay.rb +87 -0
  49. data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +26 -0
  50. data/lib/asciidoctor/syntax_highlighter/html_pipeline.rb +10 -0
  51. data/lib/asciidoctor/syntax_highlighter/prettify.rb +27 -0
  52. data/lib/asciidoctor/syntax_highlighter/pygments.rb +149 -0
  53. data/lib/asciidoctor/syntax_highlighter/rouge.rb +129 -0
  54. data/lib/asciidoctor/table.rb +73 -66
  55. data/lib/asciidoctor/timings.rb +4 -2
  56. data/lib/asciidoctor/version.rb +2 -1
  57. data/lib/asciidoctor/writer.rb +30 -0
  58. data/man/asciidoctor.1 +19 -15
  59. data/man/asciidoctor.adoc +14 -12
  60. metadata +69 -216
  61. data/CONTRIBUTING.adoc +0 -185
  62. data/Gemfile +0 -60
  63. data/Rakefile +0 -129
  64. data/bin/asciidoctor-safe +0 -15
  65. data/features/open_block.feature +0 -92
  66. data/features/pass_block.feature +0 -66
  67. data/features/step_definitions.rb +0 -49
  68. data/features/text_formatting.feature +0 -57
  69. data/features/xref.feature +0 -1039
  70. data/lib/asciidoctor/converter/base.rb +0 -59
  71. data/lib/asciidoctor/converter/docbook45.rb +0 -93
  72. data/lib/asciidoctor/converter/factory.rb +0 -226
  73. data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +0 -6
  74. data/lib/asciidoctor/core_ext/1.8.7/concurrent/hash.rb +0 -5
  75. data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +0 -4
  76. data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +0 -6
  77. data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +0 -5
  78. data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +0 -6
  79. data/lib/asciidoctor/core_ext/1.8.7/string/limit_bytesize.rb +0 -29
  80. data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +0 -6
  81. data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +0 -6
  82. data/lib/asciidoctor/core_ext/string/limit_bytesize.rb +0 -10
  83. data/test/api_test.rb +0 -1240
  84. data/test/attribute_list_test.rb +0 -242
  85. data/test/attributes_test.rb +0 -1623
  86. data/test/blocks_test.rb +0 -3870
  87. data/test/converter_test.rb +0 -470
  88. data/test/document_test.rb +0 -1853
  89. data/test/extensions_test.rb +0 -1560
  90. data/test/fixtures/asciidoc_index.txt +0 -521
  91. data/test/fixtures/basic-docinfo-footer.html +0 -6
  92. data/test/fixtures/basic-docinfo-footer.xml +0 -8
  93. data/test/fixtures/basic-docinfo.html +0 -1
  94. data/test/fixtures/basic-docinfo.xml +0 -4
  95. data/test/fixtures/basic.asciidoc +0 -5
  96. data/test/fixtures/chapter-a.adoc +0 -3
  97. data/test/fixtures/child-include.adoc +0 -5
  98. data/test/fixtures/circle.svg +0 -9
  99. data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +0 -6
  100. data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +0 -6
  101. data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +0 -1
  102. data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +0 -3
  103. data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +0 -5
  104. data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +0 -6
  105. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +0 -3
  106. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +0 -5
  107. data/test/fixtures/custom-docinfodir/basic-docinfo.html +0 -1
  108. data/test/fixtures/custom-docinfodir/docinfo.html +0 -1
  109. data/test/fixtures/docinfo-footer.html +0 -1
  110. data/test/fixtures/docinfo-footer.xml +0 -9
  111. data/test/fixtures/docinfo.html +0 -1
  112. data/test/fixtures/docinfo.xml +0 -3
  113. data/test/fixtures/doctime-localtime.adoc +0 -2
  114. data/test/fixtures/dot.gif +0 -0
  115. data/test/fixtures/encoding.asciidoc +0 -13
  116. data/test/fixtures/file-with-missing-include.adoc +0 -1
  117. data/test/fixtures/grandchild-include.adoc +0 -3
  118. data/test/fixtures/hello-asciidoctor.pdf +0 -69
  119. data/test/fixtures/include-file.asciidoc +0 -24
  120. data/test/fixtures/include-file.jsx +0 -8
  121. data/test/fixtures/include-file.ml +0 -3
  122. data/test/fixtures/include-file.xml +0 -5
  123. data/test/fixtures/lists.adoc +0 -96
  124. data/test/fixtures/master.adoc +0 -5
  125. data/test/fixtures/mismatched-end-tag.adoc +0 -7
  126. data/test/fixtures/other-chapters.adoc +0 -11
  127. data/test/fixtures/outer-include.adoc +0 -5
  128. data/test/fixtures/parent-include-restricted.adoc +0 -5
  129. data/test/fixtures/parent-include.adoc +0 -5
  130. data/test/fixtures/sample.asciidoc +0 -30
  131. data/test/fixtures/section-a.adoc +0 -4
  132. data/test/fixtures/stylesheets/custom.css +0 -3
  133. data/test/fixtures/subdir/index.adoc +0 -3
  134. data/test/fixtures/subdir/inner-include.adoc +0 -3
  135. data/test/fixtures/subdir/middle-include.adoc +0 -5
  136. data/test/fixtures/subs-docinfo.html +0 -2
  137. data/test/fixtures/subs.adoc +0 -6
  138. data/test/fixtures/tagged-class-enclosed.rb +0 -25
  139. data/test/fixtures/tagged-class.rb +0 -23
  140. data/test/fixtures/tip.gif +0 -0
  141. data/test/fixtures/unclosed-tag.adoc +0 -3
  142. data/test/fixtures/unexpected-end-tag.adoc +0 -4
  143. data/test/invoker_test.rb +0 -745
  144. data/test/links_test.rb +0 -855
  145. data/test/lists_test.rb +0 -5151
  146. data/test/logger_test.rb +0 -211
  147. data/test/manpage_test.rb +0 -660
  148. data/test/options_test.rb +0 -262
  149. data/test/paragraphs_test.rb +0 -562
  150. data/test/parser_test.rb +0 -742
  151. data/test/paths_test.rb +0 -395
  152. data/test/preamble_test.rb +0 -173
  153. data/test/reader_test.rb +0 -2161
  154. data/test/sections_test.rb +0 -3575
  155. data/test/substitutions_test.rb +0 -2066
  156. data/test/tables_test.rb +0 -2036
  157. data/test/test_helper.rb +0 -447
  158. data/test/text_test.rb +0 -309
@@ -1,4 +1,4 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
2
  module Asciidoctor
3
3
  # Public: Handles parsing AsciiDoc attribute lists into a Hash of key/value
4
4
  # pairs. By default, attributes must each be separated by a comma and quotes
@@ -11,15 +11,15 @@ module Asciidoctor
11
11
  # attrlist = Asciidoctor::AttributeList.new('astyle')
12
12
  #
13
13
  # attrlist.parse
14
- # => {0 => 'astyle'}
14
+ # => { 0 => 'astyle' }
15
15
  #
16
16
  # attrlist.rekey(['style'])
17
- # => {'style' => 'astyle'}
17
+ # => { 'style' => 'astyle' }
18
18
  #
19
19
  # attrlist = Asciidoctor::AttributeList.new('quote, Famous Person, Famous Book (2001)')
20
20
  #
21
21
  # attrlist.parse(['style', 'attribution', 'citetitle'])
22
- # => {'style' => 'quote', 'attribution' => 'Famous Person', 'citetitle' => 'Famous Book (2001)'}
22
+ # => { 'style' => 'quote', 'attribution' => 'Famous Person', 'citetitle' => 'Famous Book (2001)' }
23
23
  #
24
24
  class AttributeList
25
25
  BACKSLASH = '\\'
@@ -44,11 +44,8 @@ class AttributeList
44
44
 
45
45
  BlankRx = /[ \t]+/
46
46
 
47
- # Public: Regular expressions for skipping blanks and delimiters
48
- SkipRxs = {
49
- :blank => BlankRx,
50
- ',' => /[ \t]*(,|$)/
51
- }
47
+ # Public: Regular expressions for skipping delimiters
48
+ SkipRxs = { ',' => /[ \t]*(,|$)/ }
52
49
 
53
50
  def initialize source, block = nil, delimiter = ','
54
51
  @scanner = ::StringScanner.new source
@@ -88,8 +85,7 @@ class AttributeList
88
85
  def self.rekey attributes, pos_attrs
89
86
  pos_attrs.each_with_index do |key, index|
90
87
  next unless key
91
- pos = index + 1
92
- if (val = attributes[pos])
88
+ if (val = attributes[index + 1])
93
89
  # QUESTION should we delete the positional key?
94
90
  attributes[key] = val
95
91
  end
@@ -98,6 +94,8 @@ class AttributeList
98
94
  attributes
99
95
  end
100
96
 
97
+ private
98
+
101
99
  def parse_attribute index = 0, pos_attrs = []
102
100
  single_quoted_value = false
103
101
  skip_blank
@@ -160,9 +158,8 @@ class AttributeList
160
158
  value = value.delete ' ' if value.include? ' '
161
159
  (value.split ',').each {|opt| @attributes[%(#{opt}-option)] = '' unless opt.empty? }
162
160
  else
163
- @attributes[%(#{value = value.strip}-option)] = ''
161
+ @attributes[%(#{value}-option)] = '' unless value.empty?
164
162
  end
165
- @attributes['options'] = value
166
163
  else
167
164
  if single_quoted_value && @block
168
165
  case name
@@ -227,6 +224,5 @@ class AttributeList
227
224
  def scan_to_quote quote
228
225
  @scanner.scan BoundaryRxs[quote]
229
226
  end
230
-
231
227
  end
232
228
  end
@@ -1,26 +1,26 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
2
  module Asciidoctor
3
3
  # Public: Methods for managing blocks of Asciidoc content in a section.
4
4
  #
5
5
  # Examples
6
6
  #
7
- # block = Asciidoctor::Block.new(parent, :paragraph, :source => '_This_ is a <test>')
7
+ # block = Asciidoctor::Block.new(parent, :paragraph, source: '_This_ is a <test>')
8
8
  # block.content
9
9
  # => "<em>This</em> is a &lt;test&gt;"
10
10
  class Block < AbstractBlock
11
11
 
12
12
  (DEFAULT_CONTENT_MODEL = {
13
13
  # TODO should probably fill in all known blocks
14
- :audio => :empty,
15
- :image => :empty,
16
- :listing => :verbatim,
17
- :literal => :verbatim,
18
- :stem => :raw,
19
- :open => :compound,
20
- :page_break => :empty,
21
- :pass => :raw,
22
- :thematic_break => :empty,
23
- :video => :empty
14
+ audio: :empty,
15
+ image: :empty,
16
+ listing: :verbatim,
17
+ literal: :verbatim,
18
+ stem: :raw,
19
+ open: :compound,
20
+ page_break: :empty,
21
+ pass: :raw,
22
+ thematic_break: :empty,
23
+ video: :empty,
24
24
  }).default = :simple
25
25
 
26
26
  # Public: Create alias for context to be consistent w/ AsciiDoc
@@ -43,7 +43,7 @@ class Block < AbstractBlock
43
43
  # the `lock_in_subs` method to resolve and assign the substitutions to this
44
44
  # block (which are resolved from the `subs` attribute, if specified, or the
45
45
  # default substitutions based on this block's context). If you want to use the
46
- # default subs for a block, pass the option `:subs => :default`. You can
46
+ # default subs for a block, pass the option `subs: :default`. You can
47
47
  # override the default subs using the `:default_subs` option.
48
48
  #--
49
49
  # QUESTION should we store source_data as lines for blocks that have compound content models?
@@ -54,16 +54,16 @@ class Block < AbstractBlock
54
54
  # FIXME feels funky; we have to be defensive to get lock_in_subs to honor override
55
55
  # FIXME does not resolve substitution groups inside Array (e.g., [:normal])
56
56
  if (subs = opts[:subs])
57
- # e.g., :subs => :defult
57
+ # e.g., subs: :defult
58
58
  # subs attribute is honored; falls back to opts[:default_subs], then built-in defaults based on context
59
59
  if subs == :default
60
60
  @default_subs = opts[:default_subs]
61
- # e.g., :subs => [:quotes]
61
+ # e.g., subs: [:quotes]
62
62
  # subs attribute is not honored
63
63
  elsif ::Array === subs
64
64
  @default_subs = subs.drop 0
65
65
  @attributes.delete 'subs'
66
- # e.g., :subs => :normal or :subs => 'normal'
66
+ # e.g., subs: :normal or subs: 'normal'
67
67
  # subs attribute is not honored
68
68
  else
69
69
  @default_subs = nil
@@ -71,8 +71,9 @@ class Block < AbstractBlock
71
71
  @attributes['subs'] = %(#{subs})
72
72
  end
73
73
  # resolve the subs eagerly only if subs option is specified
74
+ # QUESTION should we skip subsequent calls to lock_in_subs?
74
75
  lock_in_subs
75
- # e.g., :subs => nil
76
+ # e.g., subs: nil
76
77
  else
77
78
  # NOTE @subs is initialized as empty array by super constructor
78
79
  # prevent subs from being resolved
@@ -88,7 +89,7 @@ class Block < AbstractBlock
88
89
  if (raw_source = opts[:source]).nil_or_empty?
89
90
  @lines = []
90
91
  elsif ::String === raw_source
91
- @lines = Helpers.normalize_lines_from_string raw_source
92
+ @lines = Helpers.prepare_source_string raw_source
92
93
  else
93
94
  @lines = raw_source.drop 0
94
95
  end
@@ -101,7 +102,7 @@ class Block < AbstractBlock
101
102
  #
102
103
  # doc = Asciidoctor::Document.new
103
104
  # block = Asciidoctor::Block.new(doc, :paragraph,
104
- # :source => '_This_ is what happens when you <meet> a stranger in the <alps>!')
105
+ # source: '_This_ is what happens when you <meet> a stranger in the <alps>!')
105
106
  # block.content
106
107
  # => "<em>This</em> is what happens when you &lt;meet&gt; a stranger in the &lt;alps&gt;!"
107
108
  def content
@@ -1,4 +1,4 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
2
  module Asciidoctor
3
3
  # Public: Maintains a catalog of callouts and their associations.
4
4
  class Callouts
@@ -28,7 +28,7 @@ class Callouts
28
28
  #
29
29
  # Returns The unique String id of this callout
30
30
  def register li_ordinal
31
- current_list << { :ordinal => li_ordinal.to_i, :id => (id = generate_next_callout_id) }
31
+ current_list << { ordinal: li_ordinal.to_i, id: (id = generate_next_callout_id) }
32
32
  @co_index += 1
33
33
  id
34
34
  end
@@ -93,6 +93,8 @@ class Callouts
93
93
  nil
94
94
  end
95
95
 
96
+ private
97
+
96
98
  # Internal: Generate a unique id for the callout based on the internal indexes
97
99
  #
98
100
  # Returns A unique String id for this callout
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'optparse'
2
- require 'asciidoctor/cli/options'
3
- require 'asciidoctor/cli/invoker'
3
+ require_relative 'cli/options'
4
+ require_relative 'cli/invoker'
@@ -1,8 +1,9 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
2
  module Asciidoctor
3
3
  module Cli
4
4
  # Public Invocation class for starting Asciidoctor via CLI
5
5
  class Invoker
6
+ include Logging
6
7
 
7
8
  attr_reader :options
8
9
  attr_reader :documents
@@ -32,8 +33,8 @@ module Asciidoctor
32
33
  def invoke!
33
34
  return unless @options
34
35
 
35
- old_verbose = $VERBOSE
36
36
  old_logger = old_logger_level = nil
37
+ old_verbose, $VERBOSE = $VERBOSE, @options[:warnings]
37
38
  opts = {}
38
39
  infiles = []
39
40
  outfile = nil
@@ -61,18 +62,14 @@ module Asciidoctor
61
62
  when :timings
62
63
  show_timings = val
63
64
  when :trace
64
- # currently does nothing
65
+ # no assignment
65
66
  when :verbose
66
67
  case val
67
68
  when 0
68
69
  $VERBOSE = nil
69
- old_logger = LoggerManager.logger
70
- LoggerManager.logger = NullLogger.new
71
- when 1
72
- $VERBOSE = false
70
+ old_logger, LoggerManager.logger = logger, NullLogger.new
73
71
  when 2
74
- $VERBOSE = true
75
- old_logger_level, LoggerManager.logger.level = LoggerManager.logger.level, ::Logger::Severity::DEBUG
72
+ old_logger_level, logger.level = logger.level, ::Logger::Severity::DEBUG
76
73
  end
77
74
  else
78
75
  opts[key] = val unless val.nil?
@@ -101,16 +98,16 @@ module Asciidoctor
101
98
  if stdin
102
99
  # allows use of block to supply stdin, particularly useful for tests
103
100
  input = block_given? ? yield : STDIN
104
- input_opts = opts.merge :to_file => tofile
101
+ input_opts = opts.merge to_file: tofile
105
102
  if show_timings
106
- @documents << (::Asciidoctor.convert input, (input_opts.merge :timings => (timings = Timings.new)))
103
+ @documents << (::Asciidoctor.convert input, (input_opts.merge timings: (timings = Timings.new)))
107
104
  timings.print_report err, '-'
108
105
  else
109
106
  @documents << (::Asciidoctor.convert input, input_opts)
110
107
  end
111
108
  else
112
109
  infiles.each do |infile|
113
- input_opts = opts.merge :to_file => tofile
110
+ input_opts = opts.merge to_file: tofile
114
111
  if abs_srcdir_posix && (input_opts.key? :to_dir)
115
112
  abs_indir = ::File.dirname ::File.expand_path infile
116
113
  if non_posix_env
@@ -123,29 +120,25 @@ module Asciidoctor
123
120
  end
124
121
  end
125
122
  if show_timings
126
- @documents << (::Asciidoctor.convert_file infile, (input_opts.merge :timings => (timings = Timings.new)))
123
+ @documents << (::Asciidoctor.convert_file infile, (input_opts.merge timings: (timings = Timings.new)))
127
124
  timings.print_report err, infile
128
125
  else
129
126
  @documents << (::Asciidoctor.convert_file infile, input_opts)
130
127
  end
131
128
  end
132
129
  end
133
- @code = 1 if ((logger = LoggerManager.logger).respond_to? :max_severity) && logger.max_severity && logger.max_severity >= opts[:failure_level]
130
+ @code = 1 if (logger.respond_to? :max_severity) && logger.max_severity && logger.max_severity >= opts[:failure_level]
134
131
  rescue ::Exception => e
135
132
  if ::SignalException === e
136
133
  @code = e.signo
137
- # add extra endline if Ctrl+C is used
134
+ # add extra newline if Ctrl+C is used
138
135
  err.puts if ::Interrupt === e
139
136
  else
140
137
  @code = (e.respond_to? :status) ? e.status : 1
141
138
  if @options[:trace]
142
139
  raise e
143
140
  else
144
- if ::RuntimeError === e
145
- err.puts %(#{e.message} (#{e.class}))
146
- else
147
- err.puts e.message
148
- end
141
+ err.puts ::RuntimeError === e ? %(#{e.message} (#{e.class})) : e.message
149
142
  err.puts ' Use --trace for backtrace'
150
143
  end
151
144
  end
@@ -155,7 +148,7 @@ module Asciidoctor
155
148
  if old_logger
156
149
  LoggerManager.logger = old_logger
157
150
  elsif old_logger_level
158
- LoggerManager.logger.level = old_logger_level
151
+ logger.level = old_logger_level
159
152
  end
160
153
  end
161
154
 
@@ -1,4 +1,4 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
2
  module Asciidoctor
3
3
  module Cli
4
4
  FS = '/'
@@ -23,6 +23,7 @@ module Asciidoctor
23
23
  end
24
24
  self[:eruby] = options[:eruby] || nil
25
25
  self[:verbose] = options[:verbose] || 1
26
+ self[:warnings] = options[:warnings] || false
26
27
  self[:load_paths] = options[:load_paths] || nil
27
28
  self[:requires] = options[:requires] || nil
28
29
  self[:base_dir] = options[:base_dir]
@@ -39,15 +40,15 @@ module Asciidoctor
39
40
 
40
41
  def parse!(args)
41
42
  opts_parser = ::OptionParser.new do |opts|
42
- opts.banner = <<-EOS
43
- Usage: asciidoctor [OPTION]... FILE...
44
- Translate the AsciiDoc source FILE or FILE(s) into the backend output format (e.g., HTML 5, DocBook 4.5, etc.)
45
- By default, the output is written to a file with the basename of the source file and the appropriate extension.
46
- Example: asciidoctor -b html5 source.asciidoc
43
+ opts.banner = <<~'EOS'
44
+ Usage: asciidoctor [OPTION]... FILE...
45
+ Translate the AsciiDoc source FILE or FILE(s) into the backend output format (e.g., HTML 5, DocBook 5, etc.)
46
+ By default, the output is written to a file with the basename of the source file and the appropriate extension.
47
+ Example: asciidoctor -b html5 source.asciidoc
47
48
 
48
49
  EOS
49
50
 
50
- opts.on('-b', '--backend BACKEND', 'set output format backend: [html5, xhtml5, docbook5, docbook45, manpage] (default: html5)',
51
+ opts.on('-b', '--backend BACKEND', 'set output format backend: [html5, xhtml5, docbook5, manpage] (default: html5)',
51
52
  'additional backends are supported via extensions (e.g., pdf, latex)') do |backend|
52
53
  self[:attributes]['backend'] = backend
53
54
  end
@@ -82,8 +83,9 @@ Example: asciidoctor -b html5 source.asciidoc
82
83
  opts.on('-a', '--attribute key[=value]', 'a document attribute to set in the form of key, key! or key=value pair',
83
84
  'unless @ is appended to the value, this attributes takes precedence over attributes',
84
85
  'defined in the source document') do |attr|
85
- key, val = attr.split '=', 2
86
- val = val ? (FORCE_ENCODING ? (val.force_encoding ::Encoding::UTF_8) : val) : ''
86
+ next if (attr = attr.rstrip).empty? || attr == '='
87
+ attr = attr.encode UTF_8 unless attr.encoding == UTF_8
88
+ key, _, val = attr.partition '='
87
89
  self[:attributes][key] = val
88
90
  end
89
91
  opts.on('-T', '--template-dir DIR', 'a directory containing custom converter templates that override the built-in converter (requires tilt gem)',
@@ -118,42 +120,47 @@ Example: asciidoctor -b html5 source.asciidoc
118
120
  end
119
121
  opts.on('--failure-level LEVEL', %w(warning WARNING error ERROR), 'set minimum logging level that triggers a non-zero exit code: [WARN, ERROR] (default: FATAL)') do |level|
120
122
  level = 'WARN' if (level = level.upcase) == 'WARNING'
121
- self[:failure_level] = ::Logger::Severity.const_get level
123
+ self[:failure_level] = ::Logger::Severity.const_get level, false
122
124
  end
123
- opts.on('-q', '--quiet', 'suppress warnings (default: false)') do |verbose|
125
+ opts.on('-q', '--quiet', 'silence application log messages and script warnings (default: false)') do |verbose|
124
126
  self[:verbose] = 0
125
127
  end
126
- opts.on('--trace', 'include backtrace information on errors (default: false)') do |trace|
128
+ opts.on('--trace', 'include backtrace information when reporting errors (default: false)') do |trace|
127
129
  self[:trace] = true
128
130
  end
129
131
  opts.on('-v', '--verbose', 'enable verbose mode (default: false)') do |verbose|
130
132
  self[:verbose] = 2
131
133
  end
132
- opts.on('-t', '--timings', 'enable timings mode (default: false)') do |timing|
134
+ opts.on('-w', '--warnings', 'turn on script warnings (default: false)') do |warnings|
135
+ self[:warnings] = true
136
+ end
137
+ opts.on('-t', '--timings', 'print timings report (default: false)') do |timing|
133
138
  self[:timings] = true
134
139
  end
135
-
136
- opts.on_tail('-h', '--help [TOPIC]', 'print the help message',
137
- 'show the command usage if TOPIC is not specified (or not recognized)',
140
+ opts.on_tail('-h', '--help [TOPIC]', 'print a help message',
141
+ 'show this usage if TOPIC is not specified or recognized',
142
+ 'show an overview of the AsciiDoc syntax if TOPIC is syntax',
138
143
  'dump the Asciidoctor man page (in troff/groff format) if TOPIC is manpage') do |topic|
139
- if topic == 'manpage'
140
- if (manpage_path = ENV['ASCIIDOCTOR_MANPAGE_PATH'])
144
+ case topic
145
+ # use `asciidoctor -h manpage | man -l -` to view with man pager
146
+ when 'manpage'
147
+ if (manpage_path = ::ENV['ASCIIDOCTOR_MANPAGE_PATH'])
141
148
  if ::File.exist? manpage_path
142
149
  if manpage_path.end_with? '.gz'
143
150
  require 'zlib' unless defined? ::Zlib::GzipReader
144
151
  $stdout.puts ::Zlib::GzipReader.open(manpage_path) {|gz| gz.read }
145
152
  else
146
- $stdout.puts ::IO.read manpage_path
153
+ $stdout.puts ::File.read manpage_path
147
154
  end
148
155
  else
149
156
  $stderr.puts %(asciidoctor: FAILED: manual page not found: #{manpage_path})
150
157
  return 1
151
158
  end
152
- elsif ::File.exist?(manpage_path = (::File.join ::Asciidoctor::ROOT_PATH, 'man', 'asciidoctor.1'))
153
- $stdout.puts ::IO.read manpage_path
159
+ # Ruby 2.3 requires the extra brackets around the ::File.join method call
160
+ elsif ::File.exist? (manpage_path = (::File.join ROOT_DIR, 'man', 'asciidoctor.1'))
161
+ $stdout.puts ::File.read manpage_path
154
162
  else
155
- require 'open3' unless defined? ::Open3.popen3
156
- manpage_path = ::Open3.popen3('man -w asciidoctor') {|_, out| out.read }.chop rescue ''
163
+ manpage_path = `man -w asciidoctor`.chop rescue ''
157
164
  if manpage_path.empty?
158
165
  $stderr.puts 'asciidoctor: FAILED: manual page not found; try `man asciidoctor`'
159
166
  return 1
@@ -161,26 +168,32 @@ Example: asciidoctor -b html5 source.asciidoc
161
168
  require 'zlib' unless defined? ::Zlib::GzipReader
162
169
  $stdout.puts ::Zlib::GzipReader.open(manpage_path) {|gz| gz.read }
163
170
  else
164
- $stdout.puts ::IO.read manpage_path
171
+ $stdout.puts ::File.read manpage_path
165
172
  end
166
173
  end
174
+ when 'syntax'
175
+ # Ruby 2.3 requires the extra brackets around the ::File.join method call
176
+ if ::File.exist? (syntax_path = (::File.join ROOT_DIR, 'data', 'reference', 'syntax.adoc'))
177
+ $stdout.puts ::File.read syntax_path
178
+ else
179
+ $stderr.puts 'asciidoctor: FAILED: syntax page not found; visit https://asciidoctor.org/docs'
180
+ return 1
181
+ end
167
182
  else
168
183
  $stdout.puts opts
169
184
  end
170
185
  return 0
171
186
  end
172
-
173
187
  opts.on_tail('-V', '--version', 'display the version and runtime environment (or -v if no other flags or arguments)') do
174
188
  return print_version $stdout
175
189
  end
176
-
177
190
  end
178
191
 
179
- infiles = []
192
+ old_verbose, $VERBOSE = $VERBOSE, (args.include? '-w')
180
193
  opts_parser.parse! args
181
194
 
182
195
  if args.empty?
183
- if self[:verbose] == 2
196
+ if self[:verbose] == 2 # -v flag was specified
184
197
  return print_version $stdout
185
198
  else
186
199
  $stderr.puts opts_parser
@@ -188,29 +201,28 @@ Example: asciidoctor -b html5 source.asciidoc
188
201
  end
189
202
  end
190
203
 
204
+ infiles = []
191
205
  # shave off the file to process so that options errors appear correctly
192
206
  if args.size == 1 && args[0] == '-'
193
207
  infiles << args.pop
194
208
  elsif
195
209
  args.each do |file|
196
- if file == '-' || (file.start_with? '-')
210
+ if file.start_with? '-'
197
211
  # warn, but don't panic; we may have enough to proceed, so we won't force a failure
198
212
  $stderr.puts %(asciidoctor: WARNING: extra arguments detected (unparsed arguments: '#{args.join "', '"}') or incorrect usage of stdin)
213
+ elsif ::File.file? file
214
+ infiles << file
215
+ # NOTE only attempt to glob if file is not found
199
216
  else
200
- if ::File.file? file
217
+ # Tilt backslashes in Windows paths the Ruby-friendly way
218
+ if ::File::ALT_SEPARATOR == RS && (file.include? RS)
219
+ file = file.tr RS, FS
220
+ end
221
+ if (matches = ::Dir.glob file).empty?
222
+ # NOTE if no matches, assume it's just a missing file and proceed
201
223
  infiles << file
202
- # NOTE only attempt to glob if file is not found
203
224
  else
204
- # Tilt backslashes in Windows paths the Ruby-friendly way
205
- if ::File::ALT_SEPARATOR == RS && (file.include? RS)
206
- file = file.tr RS, FS
207
- end
208
- if (matches = ::Dir.glob file).empty?
209
- # NOTE if no matches, assume it's just a missing file and proceed
210
- infiles << file
211
- else
212
- infiles.concat matches
213
- end
225
+ infiles.concat matches
214
226
  end
215
227
  end
216
228
  end
@@ -236,11 +248,11 @@ Example: asciidoctor -b html5 source.asciidoc
236
248
 
237
249
  self[:input_files] = infiles
238
250
 
239
- self.delete(:attributes) if self[:attributes].empty?
251
+ self.delete :attributes if self[:attributes].empty?
240
252
 
241
253
  if self[:template_dirs]
242
254
  begin
243
- require 'tilt' unless defined? ::Tilt::VERSION
255
+ require 'tilt' unless defined? ::Tilt.new
244
256
  rescue ::LoadError
245
257
  raise $! if self[:trace]
246
258
  $stderr.puts 'asciidoctor: FAILED: \'tilt\' could not be loaded'
@@ -253,13 +265,13 @@ Example: asciidoctor -b html5 source.asciidoc
253
265
  end
254
266
 
255
267
  if (load_paths = self[:load_paths])
256
- (self[:load_paths] = load_paths.uniq).reverse_each do |path|
257
- $:.unshift ::File.expand_path(path)
258
- end
268
+ load_paths.uniq!
269
+ load_paths.reverse_each {|path| $:.unshift ::File.expand_path path }
259
270
  end
260
271
 
261
272
  if (requires = self[:requires])
262
- (self[:requires] = requires.uniq).each do |path|
273
+ requires.uniq!
274
+ requires.each do |path|
263
275
  begin
264
276
  require path
265
277
  rescue ::LoadError
@@ -282,18 +294,16 @@ Example: asciidoctor -b html5 source.asciidoc
282
294
  $stderr.puts %(asciidoctor: #{$!.message})
283
295
  $stdout.puts opts_parser
284
296
  return 1
297
+ ensure
298
+ $VERBOSE = old_verbose
285
299
  end
286
300
 
287
301
  def print_version os = $stdout
288
302
  os.puts %(Asciidoctor #{::Asciidoctor::VERSION} [https://asciidoctor.org])
289
- if ::RUBY_MIN_VERSION_1_9
290
- encoding_info = { 'lc' => 'locale', 'fs' => 'filesystem', 'in' => 'internal', 'ex' => 'external' }.map do |k, v|
291
- %(#{k}:#{v == 'internal' ? (::File.open(__FILE__) {|f| f.getc }).encoding : (::Encoding.find v)})
292
- end
293
- os.puts %(Runtime Environment (#{::RUBY_DESCRIPTION}) (#{encoding_info.join ' '}))
294
- else
295
- os.puts %(Runtime Environment (#{::RUBY_DESCRIPTION}))
303
+ encoding_info = { 'lc' => 'locale', 'fs' => 'filesystem', 'in' => 'internal', 'ex' => 'external' }.map do |k, v|
304
+ %(#{k}:#{v == 'internal' ? (::File.open(__FILE__) {|f| f.getc.encoding }) : (::Encoding.find v)})
296
305
  end
306
+ os.puts %(Runtime Environment (#{::RUBY_DESCRIPTION}) (#{encoding_info.join ' '}))
297
307
  0
298
308
  end
299
309
  end