asciidoctor 1.5.8 → 2.0.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
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