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.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +162 -17
- data/LICENSE +1 -1
- data/README-de.adoc +12 -13
- data/README-fr.adoc +11 -12
- data/README-jp.adoc +11 -12
- data/README-zh_CN.adoc +12 -13
- data/README.adoc +6 -7
- data/asciidoctor.gemspec +19 -24
- data/bin/asciidoctor +5 -4
- data/data/reference/syntax.adoc +283 -0
- data/data/stylesheets/asciidoctor-default.css +56 -52
- data/data/stylesheets/coderay-asciidoctor.css +7 -9
- data/lib/asciidoctor.rb +171 -232
- data/lib/asciidoctor/abstract_block.rb +96 -105
- data/lib/asciidoctor/abstract_node.rb +118 -139
- data/lib/asciidoctor/attribute_list.rb +10 -14
- data/lib/asciidoctor/block.rb +20 -19
- data/lib/asciidoctor/callouts.rb +4 -2
- data/lib/asciidoctor/cli.rb +3 -2
- data/lib/asciidoctor/cli/invoker.rb +14 -21
- data/lib/asciidoctor/cli/options.rb +64 -54
- data/lib/asciidoctor/converter.rb +357 -185
- data/lib/asciidoctor/converter/composite.rb +40 -48
- data/lib/asciidoctor/converter/docbook5.rb +604 -640
- data/lib/asciidoctor/converter/html5.rb +949 -963
- data/lib/asciidoctor/converter/manpage.rb +569 -548
- data/lib/asciidoctor/converter/template.rb +231 -272
- data/lib/asciidoctor/core_ext.rb +5 -18
- data/lib/asciidoctor/core_ext/float/truncate.rb +19 -0
- data/lib/asciidoctor/core_ext/match_data/names.rb +7 -0
- data/lib/asciidoctor/core_ext/nil_or_empty.rb +1 -0
- data/lib/asciidoctor/core_ext/regexp/is_match.rb +4 -2
- data/lib/asciidoctor/document.rb +399 -377
- data/lib/asciidoctor/extensions.rb +72 -140
- data/lib/asciidoctor/helpers.rb +122 -83
- data/lib/asciidoctor/inline.rb +5 -1
- data/lib/asciidoctor/list.rb +13 -11
- data/lib/asciidoctor/logging.rb +17 -16
- data/lib/asciidoctor/parser.rb +390 -423
- data/lib/asciidoctor/path_resolver.rb +10 -5
- data/lib/asciidoctor/reader.rb +286 -263
- data/lib/asciidoctor/rouge_ext.rb +39 -0
- data/lib/asciidoctor/section.rb +9 -8
- data/lib/asciidoctor/stylesheets.rb +19 -37
- data/lib/asciidoctor/substitutors.rb +364 -509
- data/lib/asciidoctor/syntax_highlighter.rb +238 -0
- data/lib/asciidoctor/syntax_highlighter/coderay.rb +87 -0
- data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +26 -0
- data/lib/asciidoctor/syntax_highlighter/html_pipeline.rb +10 -0
- data/lib/asciidoctor/syntax_highlighter/prettify.rb +27 -0
- data/lib/asciidoctor/syntax_highlighter/pygments.rb +149 -0
- data/lib/asciidoctor/syntax_highlighter/rouge.rb +129 -0
- data/lib/asciidoctor/table.rb +73 -66
- data/lib/asciidoctor/timings.rb +4 -2
- data/lib/asciidoctor/version.rb +2 -1
- data/lib/asciidoctor/writer.rb +30 -0
- data/man/asciidoctor.1 +19 -15
- data/man/asciidoctor.adoc +14 -12
- metadata +69 -216
- data/CONTRIBUTING.adoc +0 -185
- data/Gemfile +0 -60
- data/Rakefile +0 -129
- data/bin/asciidoctor-safe +0 -15
- data/features/open_block.feature +0 -92
- data/features/pass_block.feature +0 -66
- data/features/step_definitions.rb +0 -49
- data/features/text_formatting.feature +0 -57
- data/features/xref.feature +0 -1039
- data/lib/asciidoctor/converter/base.rb +0 -59
- data/lib/asciidoctor/converter/docbook45.rb +0 -93
- data/lib/asciidoctor/converter/factory.rb +0 -226
- data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/concurrent/hash.rb +0 -5
- data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +0 -4
- data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +0 -5
- data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/string/limit_bytesize.rb +0 -29
- data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +0 -6
- data/lib/asciidoctor/core_ext/string/limit_bytesize.rb +0 -10
- data/test/api_test.rb +0 -1240
- data/test/attribute_list_test.rb +0 -242
- data/test/attributes_test.rb +0 -1623
- data/test/blocks_test.rb +0 -3870
- data/test/converter_test.rb +0 -470
- data/test/document_test.rb +0 -1853
- data/test/extensions_test.rb +0 -1560
- data/test/fixtures/asciidoc_index.txt +0 -521
- data/test/fixtures/basic-docinfo-footer.html +0 -6
- data/test/fixtures/basic-docinfo-footer.xml +0 -8
- data/test/fixtures/basic-docinfo.html +0 -1
- data/test/fixtures/basic-docinfo.xml +0 -4
- data/test/fixtures/basic.asciidoc +0 -5
- data/test/fixtures/chapter-a.adoc +0 -3
- data/test/fixtures/child-include.adoc +0 -5
- data/test/fixtures/circle.svg +0 -9
- data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +0 -6
- data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +0 -6
- data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +0 -1
- data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +0 -3
- data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +0 -5
- data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +0 -6
- data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +0 -3
- data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +0 -5
- data/test/fixtures/custom-docinfodir/basic-docinfo.html +0 -1
- data/test/fixtures/custom-docinfodir/docinfo.html +0 -1
- data/test/fixtures/docinfo-footer.html +0 -1
- data/test/fixtures/docinfo-footer.xml +0 -9
- data/test/fixtures/docinfo.html +0 -1
- data/test/fixtures/docinfo.xml +0 -3
- data/test/fixtures/doctime-localtime.adoc +0 -2
- data/test/fixtures/dot.gif +0 -0
- data/test/fixtures/encoding.asciidoc +0 -13
- data/test/fixtures/file-with-missing-include.adoc +0 -1
- data/test/fixtures/grandchild-include.adoc +0 -3
- data/test/fixtures/hello-asciidoctor.pdf +0 -69
- data/test/fixtures/include-file.asciidoc +0 -24
- data/test/fixtures/include-file.jsx +0 -8
- data/test/fixtures/include-file.ml +0 -3
- data/test/fixtures/include-file.xml +0 -5
- data/test/fixtures/lists.adoc +0 -96
- data/test/fixtures/master.adoc +0 -5
- data/test/fixtures/mismatched-end-tag.adoc +0 -7
- data/test/fixtures/other-chapters.adoc +0 -11
- data/test/fixtures/outer-include.adoc +0 -5
- data/test/fixtures/parent-include-restricted.adoc +0 -5
- data/test/fixtures/parent-include.adoc +0 -5
- data/test/fixtures/sample.asciidoc +0 -30
- data/test/fixtures/section-a.adoc +0 -4
- data/test/fixtures/stylesheets/custom.css +0 -3
- data/test/fixtures/subdir/index.adoc +0 -3
- data/test/fixtures/subdir/inner-include.adoc +0 -3
- data/test/fixtures/subdir/middle-include.adoc +0 -5
- data/test/fixtures/subs-docinfo.html +0 -2
- data/test/fixtures/subs.adoc +0 -6
- data/test/fixtures/tagged-class-enclosed.rb +0 -25
- data/test/fixtures/tagged-class.rb +0 -23
- data/test/fixtures/tip.gif +0 -0
- data/test/fixtures/unclosed-tag.adoc +0 -3
- data/test/fixtures/unexpected-end-tag.adoc +0 -4
- data/test/invoker_test.rb +0 -745
- data/test/links_test.rb +0 -855
- data/test/lists_test.rb +0 -5151
- data/test/logger_test.rb +0 -211
- data/test/manpage_test.rb +0 -660
- data/test/options_test.rb +0 -262
- data/test/paragraphs_test.rb +0 -562
- data/test/parser_test.rb +0 -742
- data/test/paths_test.rb +0 -395
- data/test/preamble_test.rb +0 -173
- data/test/reader_test.rb +0 -2161
- data/test/sections_test.rb +0 -3575
- data/test/substitutions_test.rb +0 -2066
- data/test/tables_test.rb +0 -2036
- data/test/test_helper.rb +0 -447
- data/test/text_test.rb +0 -309
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
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
|
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
|
-
|
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
|
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
|
data/lib/asciidoctor/block.rb
CHANGED
@@ -1,26 +1,26 @@
|
|
1
|
-
#
|
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, :
|
7
|
+
# block = Asciidoctor::Block.new(parent, :paragraph, source: '_This_ is a <test>')
|
8
8
|
# block.content
|
9
9
|
# => "<em>This</em> is a <test>"
|
10
10
|
class Block < AbstractBlock
|
11
11
|
|
12
12
|
(DEFAULT_CONTENT_MODEL = {
|
13
13
|
# TODO should probably fill in all known blocks
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
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
|
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., :
|
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., :
|
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., :
|
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., :
|
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.
|
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
|
-
# :
|
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 <meet> a stranger in the <alps>!"
|
107
108
|
def content
|
data/lib/asciidoctor/callouts.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
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 << { :
|
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
|
data/lib/asciidoctor/cli.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
#
|
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
|
-
#
|
65
|
+
# no assignment
|
65
66
|
when :verbose
|
66
67
|
case val
|
67
68
|
when 0
|
68
69
|
$VERBOSE = nil
|
69
|
-
old_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
|
-
|
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 :
|
101
|
+
input_opts = opts.merge to_file: tofile
|
105
102
|
if show_timings
|
106
|
-
@documents << (::Asciidoctor.convert input, (input_opts.merge :
|
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 :
|
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 :
|
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 (
|
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
|
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
|
-
|
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
|
-
|
151
|
+
logger.level = old_logger_level
|
159
152
|
end
|
160
153
|
end
|
161
154
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
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 =
|
43
|
-
Usage: asciidoctor [OPTION]... FILE...
|
44
|
-
Translate the AsciiDoc source FILE or FILE(s) into the backend output format (e.g., HTML 5, DocBook
|
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,
|
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
|
-
|
86
|
-
|
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', '
|
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
|
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('-
|
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
|
-
|
137
|
-
'show the
|
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
|
-
|
140
|
-
|
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 ::
|
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
|
-
|
153
|
-
|
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
|
-
|
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 ::
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
-
|
257
|
-
|
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
|
-
|
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
|
-
|
290
|
-
|
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
|