asciidoctor 2.0.10 → 2.0.15
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.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +211 -22
- data/LICENSE +1 -1
- data/README-de.adoc +12 -13
- data/README-fr.adoc +11 -15
- data/README-jp.adoc +9 -17
- data/README-zh_CN.adoc +17 -18
- data/README.adoc +140 -132
- data/asciidoctor.gemspec +6 -6
- data/data/locale/attributes-ar.adoc +4 -3
- data/data/locale/attributes-be.adoc +23 -0
- data/data/locale/attributes-bg.adoc +4 -3
- data/data/locale/attributes-ca.adoc +6 -5
- data/data/locale/attributes-cs.adoc +4 -3
- data/data/locale/attributes-da.adoc +6 -5
- data/data/locale/attributes-de.adoc +4 -4
- data/data/locale/attributes-en.adoc +4 -4
- data/data/locale/attributes-es.adoc +6 -5
- data/data/locale/attributes-fa.adoc +4 -3
- data/data/locale/attributes-fi.adoc +4 -3
- data/data/locale/attributes-fr.adoc +6 -5
- data/data/locale/attributes-hu.adoc +4 -3
- data/data/locale/attributes-id.adoc +4 -3
- data/data/locale/attributes-it.adoc +6 -5
- data/data/locale/attributes-ja.adoc +4 -3
- data/data/locale/{attributes-kr.adoc → attributes-ko.adoc} +4 -3
- data/data/locale/attributes-nb.adoc +4 -3
- data/data/locale/attributes-nl.adoc +6 -5
- data/data/locale/attributes-nn.adoc +4 -3
- data/data/locale/attributes-pl.adoc +8 -7
- data/data/locale/attributes-pt.adoc +6 -5
- data/data/locale/attributes-pt_BR.adoc +6 -5
- data/data/locale/attributes-ro.adoc +4 -3
- data/data/locale/attributes-ru.adoc +6 -5
- data/data/locale/attributes-sr.adoc +4 -4
- data/data/locale/attributes-sr_Latn.adoc +4 -4
- data/data/locale/attributes-sv.adoc +4 -4
- data/data/locale/attributes-tr.adoc +4 -3
- data/data/locale/attributes-uk.adoc +6 -5
- data/data/locale/attributes-zh_CN.adoc +4 -3
- data/data/locale/attributes-zh_TW.adoc +4 -3
- data/data/reference/syntax.adoc +14 -7
- data/data/stylesheets/asciidoctor-default.css +27 -28
- data/lib/asciidoctor.rb +38 -12
- data/lib/asciidoctor/abstract_block.rb +9 -4
- data/lib/asciidoctor/abstract_node.rb +16 -6
- data/lib/asciidoctor/attribute_list.rb +64 -72
- data/lib/asciidoctor/cli/invoker.rb +2 -0
- data/lib/asciidoctor/cli/options.rb +10 -9
- data/lib/asciidoctor/convert.rb +167 -162
- data/lib/asciidoctor/converter.rb +13 -12
- data/lib/asciidoctor/converter/docbook5.rb +29 -12
- data/lib/asciidoctor/converter/html5.rb +69 -46
- data/lib/asciidoctor/converter/manpage.rb +68 -49
- data/lib/asciidoctor/converter/template.rb +3 -0
- data/lib/asciidoctor/document.rb +43 -50
- data/lib/asciidoctor/extensions.rb +2 -4
- data/lib/asciidoctor/helpers.rb +20 -15
- data/lib/asciidoctor/load.rb +102 -101
- data/lib/asciidoctor/parser.rb +40 -32
- data/lib/asciidoctor/path_resolver.rb +14 -12
- data/lib/asciidoctor/reader.rb +22 -13
- data/lib/asciidoctor/rx.rb +7 -6
- data/lib/asciidoctor/substitutors.rb +78 -57
- data/lib/asciidoctor/syntax_highlighter.rb +8 -5
- data/lib/asciidoctor/syntax_highlighter/coderay.rb +1 -1
- data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +12 -4
- data/lib/asciidoctor/syntax_highlighter/prettify.rb +7 -4
- data/lib/asciidoctor/syntax_highlighter/pygments.rb +6 -7
- data/lib/asciidoctor/syntax_highlighter/rouge.rb +33 -19
- data/lib/asciidoctor/table.rb +52 -23
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +8 -8
- data/man/asciidoctor.adoc +4 -4
- metadata +16 -15
data/lib/asciidoctor.rb
CHANGED
@@ -136,8 +136,8 @@ module Asciidoctor
|
|
136
136
|
# Compliance value: true
|
137
137
|
define :underline_style_section_titles, true
|
138
138
|
|
139
|
-
# Asciidoctor will unwrap the content in a preamble
|
140
|
-
#
|
139
|
+
# Asciidoctor will unwrap the content in a preamble if the document has a
|
140
|
+
# title and no sections, then discard the empty preamble.
|
141
141
|
# Compliance value: false
|
142
142
|
define :unwrap_standalone_preamble, true
|
143
143
|
|
@@ -148,7 +148,7 @@ module Asciidoctor
|
|
148
148
|
# Compliance value: 'drop-line'
|
149
149
|
define :attribute_missing, 'skip'
|
150
150
|
|
151
|
-
# AsciiDoc drops lines that contain an attribute
|
151
|
+
# AsciiDoc drops lines that contain an attribute unassignment.
|
152
152
|
# This behavior may need to be tuned depending on the circumstances.
|
153
153
|
# Compliance value: 'drop-line'
|
154
154
|
define :attribute_undefined, 'drop-line'
|
@@ -296,7 +296,7 @@ module Asciidoctor
|
|
296
296
|
DELIMITED_BLOCK_TAILS = {}.tap {|accum| DELIMITED_BLOCKS.each_key {|k| accum[k] = k[k.length - 1] if k.length == 4 } }
|
297
297
|
|
298
298
|
# NOTE the 'figure' key as a string is historical and used by image blocks
|
299
|
-
|
299
|
+
CAPTION_ATTRIBUTE_NAMES = { example: 'example-caption', 'figure' => 'figure-caption', listing: 'listing-caption', table: 'table-caption' }
|
300
300
|
|
301
301
|
LAYOUT_BREAK_CHARS = {
|
302
302
|
'\'' => :thematic_break,
|
@@ -332,7 +332,7 @@ module Asciidoctor
|
|
332
332
|
|
333
333
|
LIST_CONTINUATION = '+'
|
334
334
|
|
335
|
-
# NOTE AsciiDoc
|
335
|
+
# NOTE AsciiDoc.py allows + to be preceded by TAB; Asciidoctor does not
|
336
336
|
HARD_LINE_BREAK = ' +'
|
337
337
|
|
338
338
|
LINE_CONTINUATION = ' \\'
|
@@ -357,9 +357,35 @@ module Asciidoctor
|
|
357
357
|
|
358
358
|
FONT_AWESOME_VERSION = '4.7.0'
|
359
359
|
|
360
|
-
HIGHLIGHT_JS_VERSION = '9.
|
361
|
-
|
362
|
-
MATHJAX_VERSION = '2.7.
|
360
|
+
HIGHLIGHT_JS_VERSION = '9.18.3'
|
361
|
+
|
362
|
+
MATHJAX_VERSION = '2.7.9'
|
363
|
+
|
364
|
+
DEFAULT_ATTRIBUTES = {
|
365
|
+
'appendix-caption' => 'Appendix',
|
366
|
+
'appendix-refsig' => 'Appendix',
|
367
|
+
'caution-caption' => 'Caution',
|
368
|
+
'chapter-refsig' => 'Chapter',
|
369
|
+
#'encoding' => 'UTF-8',
|
370
|
+
'example-caption' => 'Example',
|
371
|
+
'figure-caption' => 'Figure',
|
372
|
+
'important-caption' => 'Important',
|
373
|
+
'last-update-label' => 'Last updated',
|
374
|
+
#'listing-caption' => 'Listing',
|
375
|
+
'note-caption' => 'Note',
|
376
|
+
'part-refsig' => 'Part',
|
377
|
+
#'preface-title' => 'Preface',
|
378
|
+
'prewrap' => '',
|
379
|
+
'sectids' => '',
|
380
|
+
'section-refsig' => 'Section',
|
381
|
+
'table-caption' => 'Table',
|
382
|
+
'tip-caption' => 'Tip',
|
383
|
+
'toc-placement' => 'auto',
|
384
|
+
'toc-title' => 'Table of Contents',
|
385
|
+
'untitled-label' => 'Untitled',
|
386
|
+
'version-label' => 'Version',
|
387
|
+
'warning-caption' => 'Warning',
|
388
|
+
}
|
363
389
|
|
364
390
|
# attributes which be changed throughout the flow of the document (e.g., sectnums)
|
365
391
|
FLEXIBLE_ATTRIBUTES = ['sectnums']
|
@@ -433,9 +459,9 @@ module Asciidoctor
|
|
433
459
|
[:emphasis, :unconstrained, /\\?(?:\[([^\]]+)\])?__(#{CC_ALL}+?)__/m],
|
434
460
|
# _emphasis_
|
435
461
|
[:emphasis, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?_(\S|\S#{CC_ALL}*?\S)_(?!#{CG_WORD})/m],
|
436
|
-
# ##mark## (referred to in AsciiDoc
|
462
|
+
# ##mark## (referred to in AsciiDoc.py as unquoted)
|
437
463
|
[:mark, :unconstrained, /\\?(?:\[([^\]]+)\])?##(#{CC_ALL}+?)##/m],
|
438
|
-
# #mark# (referred to in AsciiDoc
|
464
|
+
# #mark# (referred to in AsciiDoc.py as unquoted)
|
439
465
|
[:mark, :constrained, /(^|[^#{CC_WORD}&;:}])(?:\[([^\]]+)\])?#(\S|\S#{CC_ALL}*?\S)#(?!#{CG_WORD})/m],
|
440
466
|
# ^superscript^
|
441
467
|
[:superscript, :unconstrained, /\\?(?:\[([^\]]+)\])?\^(\S+?)\^/],
|
@@ -511,8 +537,8 @@ module Asciidoctor
|
|
511
537
|
end unless RUBY_ENGINE == 'opal'
|
512
538
|
|
513
539
|
unless RUBY_ENGINE == 'opal'
|
514
|
-
autoload :SyntaxHighlighter, %(#{
|
515
|
-
autoload :Timings, %(#{
|
540
|
+
autoload :SyntaxHighlighter, %(#{__dir__}/asciidoctor/syntax_highlighter)
|
541
|
+
autoload :Timings, %(#{__dir__}/asciidoctor/timings)
|
516
542
|
end
|
517
543
|
end
|
518
544
|
|
@@ -141,6 +141,11 @@ class AbstractBlock < AbstractNode
|
|
141
141
|
(Integer @numeral) rescue @numeral
|
142
142
|
end
|
143
143
|
|
144
|
+
# Deprecated: Legacy property to set the numeral of this section by coercing the value to a String.
|
145
|
+
def number= val
|
146
|
+
@numeral = val.to_s
|
147
|
+
end
|
148
|
+
|
144
149
|
# Public: Walk the document tree and find all block-level nodes that match the specified selector (context, style, id,
|
145
150
|
# role, and/or custom filter).
|
146
151
|
#
|
@@ -338,17 +343,17 @@ class AbstractBlock < AbstractNode
|
|
338
343
|
if (val = reftext) && !val.empty?
|
339
344
|
val
|
340
345
|
# NOTE xrefstyle only applies to blocks with a title and a caption or number
|
341
|
-
elsif xrefstyle && @title &&
|
346
|
+
elsif xrefstyle && @title && !@caption.nil_or_empty?
|
342
347
|
case xrefstyle
|
343
348
|
when 'full'
|
344
349
|
quoted_title = sub_placeholder (sub_quotes @document.compat_mode ? %q(``%s'') : '"`%s`"'), title
|
345
|
-
if @numeral && (caption_attr_name =
|
350
|
+
if @numeral && (caption_attr_name = CAPTION_ATTRIBUTE_NAMES[@context]) && (prefix = @document.attributes[caption_attr_name])
|
346
351
|
%(#{prefix} #{@numeral}, #{quoted_title})
|
347
352
|
else
|
348
353
|
%(#{@caption.chomp '. '}, #{quoted_title})
|
349
354
|
end
|
350
355
|
when 'short'
|
351
|
-
if @numeral && (caption_attr_name =
|
356
|
+
if @numeral && (caption_attr_name = CAPTION_ATTRIBUTE_NAMES[@context]) && (prefix = @document.attributes[caption_attr_name])
|
352
357
|
%(#{prefix} #{@numeral})
|
353
358
|
else
|
354
359
|
@caption.chomp '. '
|
@@ -380,7 +385,7 @@ class AbstractBlock < AbstractNode
|
|
380
385
|
# Returns nothing.
|
381
386
|
def assign_caption value, caption_context = @context
|
382
387
|
unless @caption || !@title || (@caption = value || @document.attributes['caption'])
|
383
|
-
if (attr_name =
|
388
|
+
if (attr_name = CAPTION_ATTRIBUTE_NAMES[caption_context]) && (prefix = @document.attributes[attr_name])
|
384
389
|
@caption = %(#{prefix} #{@numeral = @document.increment_and_store_counter %(#{caption_context}-number), self}. )
|
385
390
|
nil
|
386
391
|
end
|
@@ -65,7 +65,7 @@ class AbstractNode
|
|
65
65
|
#
|
66
66
|
# parent - The Block to set as the parent of this Block
|
67
67
|
#
|
68
|
-
# Returns the
|
68
|
+
# Returns the value of the parent argument
|
69
69
|
def parent= parent
|
70
70
|
@parent, @document = parent, parent.document
|
71
71
|
end
|
@@ -216,6 +216,15 @@ class AbstractNode
|
|
216
216
|
(val = @attributes['role']) ? (%( #{val} ).include? %( #{name} )) : false
|
217
217
|
end
|
218
218
|
|
219
|
+
# Public: Sets the value of the role attribute on this node.
|
220
|
+
#
|
221
|
+
# names - A single role name, a space-separated String of role names, or an Array of role names
|
222
|
+
#
|
223
|
+
# Returns the value of the names argument
|
224
|
+
def role= names
|
225
|
+
@attributes['role'] = (::Array === names) ? (names.join ' ') : names
|
226
|
+
end
|
227
|
+
|
219
228
|
# Public: Adds the given role directly to this node.
|
220
229
|
#
|
221
230
|
# Returns a [Boolean] indicating whether the role was added.
|
@@ -514,6 +523,7 @@ class AbstractNode
|
|
514
523
|
# * :normalize a Boolean that indicates whether the data should be normalized (default: false)
|
515
524
|
# * :start the String relative base path to use when resolving the target (default: nil)
|
516
525
|
# * :warn_on_failure a Boolean that indicates whether warnings are issued if the target cannot be read (default: true)
|
526
|
+
# * :warn_if_empty a Boolean that indicates whether a warning is issued if contents of target is empty (default: false)
|
517
527
|
# Returns the contents of the resolved target or nil if the resolved target cannot be read
|
518
528
|
# --
|
519
529
|
# TODO refactor other methods in this class to use this method were possible (repurposing if necessary)
|
@@ -525,22 +535,22 @@ class AbstractNode
|
|
525
535
|
Helpers.require_library 'open-uri/cached', 'open-uri-cached' if doc.attr? 'cache-uri'
|
526
536
|
begin
|
527
537
|
if opts[:normalize]
|
528
|
-
(Helpers.prepare_source_string ::OpenURI.open_uri(target, URI_READ_MODE) {|f| f.read }).join LF
|
538
|
+
contents = (Helpers.prepare_source_string ::OpenURI.open_uri(target, URI_READ_MODE) {|f| f.read }).join LF
|
529
539
|
else
|
530
|
-
::OpenURI.open_uri(target, URI_READ_MODE) {|f| f.read }
|
540
|
+
contents = ::OpenURI.open_uri(target, URI_READ_MODE) {|f| f.read }
|
531
541
|
end
|
532
542
|
rescue
|
533
543
|
logger.warn %(could not retrieve contents of #{opts[:label] || 'asset'} at URI: #{target}) if opts.fetch :warn_on_failure, true
|
534
|
-
return
|
535
544
|
end
|
536
545
|
else
|
537
546
|
logger.warn %(cannot retrieve contents of #{opts[:label] || 'asset'} at URI: #{target} (allow-uri-read attribute not enabled)) if opts.fetch :warn_on_failure, true
|
538
|
-
return
|
539
547
|
end
|
540
548
|
else
|
541
549
|
target = normalize_system_path target, opts[:start], nil, target_name: (opts[:label] || 'asset')
|
542
|
-
read_asset target, normalize: opts[:normalize], warn_on_failure: (opts.fetch :warn_on_failure, true), label: opts[:label]
|
550
|
+
contents = read_asset target, normalize: opts[:normalize], warn_on_failure: (opts.fetch :warn_on_failure, true), label: opts[:label]
|
543
551
|
end
|
552
|
+
logger.warn %(contents of #{opts[:label] || 'asset'} is empty: #{target}) if contents && opts[:warn_if_empty] && contents.empty?
|
553
|
+
contents
|
544
554
|
end
|
545
555
|
|
546
556
|
# Deprecated: Check whether the specified String is a URI by
|
@@ -22,19 +22,20 @@ module Asciidoctor
|
|
22
22
|
# => { 'style' => 'quote', 'attribution' => 'Famous Person', 'citetitle' => 'Famous Book (2001)' }
|
23
23
|
#
|
24
24
|
class AttributeList
|
25
|
-
BACKSLASH = '\\'
|
26
25
|
APOS = '\''
|
26
|
+
BACKSLASH = '\\'
|
27
|
+
QUOT = '"'
|
27
28
|
|
28
29
|
# Public: Regular expressions for detecting the boundary of a value
|
29
|
-
|
30
|
-
|
30
|
+
BoundaryRx = {
|
31
|
+
QUOT => /.*?[^\\](?=")/,
|
31
32
|
APOS => /.*?[^\\](?=')/,
|
32
33
|
',' => /.*?(?=[ \t]*(,|$))/
|
33
34
|
}
|
34
35
|
|
35
36
|
# Public: Regular expressions for unescaping quoted characters
|
36
37
|
EscapedQuotes = {
|
37
|
-
|
38
|
+
QUOT => '\\"',
|
38
39
|
APOS => '\\\''
|
39
40
|
}
|
40
41
|
|
@@ -45,14 +46,16 @@ class AttributeList
|
|
45
46
|
BlankRx = /[ \t]+/
|
46
47
|
|
47
48
|
# Public: Regular expressions for skipping delimiters
|
48
|
-
|
49
|
+
SkipRx = {
|
50
|
+
',' => /[ \t]*(,|$)/
|
51
|
+
}
|
49
52
|
|
50
53
|
def initialize source, block = nil, delimiter = ','
|
51
54
|
@scanner = ::StringScanner.new source
|
52
55
|
@block = block
|
53
56
|
@delimiter = delimiter
|
54
|
-
@delimiter_skip_pattern =
|
55
|
-
@delimiter_boundary_pattern =
|
57
|
+
@delimiter_skip_pattern = SkipRx[delimiter]
|
58
|
+
@delimiter_boundary_pattern = BoundaryRx[delimiter]
|
56
59
|
@attributes = nil
|
57
60
|
end
|
58
61
|
|
@@ -65,8 +68,6 @@ class AttributeList
|
|
65
68
|
return @attributes if @attributes
|
66
69
|
|
67
70
|
@attributes = {}
|
68
|
-
# QUESTION do we want to store the attribute list as the zero-index attribute?
|
69
|
-
#attributes[0] = @scanner.string
|
70
71
|
index = 0
|
71
72
|
|
72
73
|
while parse_attribute index, positional_attrs
|
@@ -83,75 +84,73 @@ class AttributeList
|
|
83
84
|
end
|
84
85
|
|
85
86
|
def self.rekey attributes, positional_attrs
|
86
|
-
|
87
|
-
|
88
|
-
index += 1
|
89
|
-
if (val = attributes[index])
|
87
|
+
positional_attrs.each_with_index do |key, index|
|
88
|
+
if key && (val = attributes[index + 1])
|
90
89
|
# QUESTION should we delete the positional key?
|
91
90
|
attributes[key] = val
|
92
|
-
end
|
91
|
+
end
|
93
92
|
end
|
94
93
|
attributes
|
95
94
|
end
|
96
95
|
|
97
96
|
private
|
98
97
|
|
99
|
-
def parse_attribute index
|
100
|
-
|
98
|
+
def parse_attribute index, positional_attrs
|
99
|
+
continue = true
|
101
100
|
skip_blank
|
102
|
-
|
103
|
-
|
101
|
+
case @scanner.peek 1
|
102
|
+
# example: "quote" || "foo
|
103
|
+
when QUOT
|
104
104
|
name = parse_attribute_value @scanner.get_byte
|
105
|
-
|
106
|
-
|
107
|
-
elsif first == APOS
|
105
|
+
# example: 'quote' || 'foo
|
106
|
+
when APOS
|
108
107
|
name = parse_attribute_value @scanner.get_byte
|
109
|
-
|
110
|
-
single_quoted_value = true unless name.start_with? APOS
|
108
|
+
single_quoted = true unless name.start_with? APOS
|
111
109
|
else
|
112
|
-
name = scan_name
|
113
|
-
|
114
|
-
skipped = 0
|
115
|
-
c = nil
|
110
|
+
skipped = ((name = scan_name) && skip_blank) || 0
|
116
111
|
if @scanner.eos?
|
117
|
-
return
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
else
|
131
|
-
skip_blank
|
132
|
-
if @scanner.peek(1)
|
133
|
-
# example: foo="bar" || foo="ba\"zaar"
|
134
|
-
if (c = @scanner.get_byte) == '"'
|
112
|
+
return unless name || (@scanner.string.rstrip.end_with? @delimiter)
|
113
|
+
# example: quote (at eos)
|
114
|
+
continue = nil
|
115
|
+
# example: quote,
|
116
|
+
elsif (c = @scanner.get_byte) == @delimiter
|
117
|
+
@scanner.unscan
|
118
|
+
elsif name
|
119
|
+
# example: foo=...
|
120
|
+
if c == '='
|
121
|
+
skip_blank
|
122
|
+
case (c = @scanner.get_byte)
|
123
|
+
# example: foo="bar" || foo="ba\"zaar" || foo="bar
|
124
|
+
when QUOT
|
135
125
|
value = parse_attribute_value c
|
136
|
-
# example: foo='bar' || foo='ba\'zaar' || foo='ba"zaar'
|
137
|
-
|
126
|
+
# example: foo='bar' || foo='ba\'zaar' || foo='ba"zaar' || foo='bar
|
127
|
+
when APOS
|
138
128
|
value = parse_attribute_value c
|
139
|
-
|
129
|
+
single_quoted = true unless value.start_with? APOS
|
140
130
|
# example: foo=,
|
141
|
-
|
131
|
+
when @delimiter
|
132
|
+
value = ''
|
133
|
+
@scanner.unscan
|
134
|
+
# example: foo= (at eos)
|
135
|
+
when nil
|
142
136
|
value = ''
|
143
|
-
# example: foo=bar
|
137
|
+
# example: foo=bar || foo=None
|
144
138
|
else
|
145
139
|
value = %(#{c}#{scan_to_delimiter})
|
146
140
|
return true if value == 'None'
|
147
141
|
end
|
142
|
+
# example: foo bar
|
143
|
+
else
|
144
|
+
name = %(#{name}#{' ' * skipped}#{c}#{scan_to_delimiter})
|
148
145
|
end
|
146
|
+
# example: =foo= || !foo
|
147
|
+
else
|
148
|
+
name = %(#{c}#{scan_to_delimiter})
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
152
152
|
if value
|
153
|
-
# example: options="opt1,opt2,opt3"
|
154
|
-
# opts is an alias for options
|
153
|
+
# example: options="opt1,opt2,opt3" || opts="opts1,opt2,opt3"
|
155
154
|
case name
|
156
155
|
when 'options', 'opts'
|
157
156
|
if value.include? ','
|
@@ -161,7 +160,7 @@ class AttributeList
|
|
161
160
|
@attributes[%(#{value}-option)] = '' unless value.empty?
|
162
161
|
end
|
163
162
|
else
|
164
|
-
if
|
163
|
+
if single_quoted && @block
|
165
164
|
case name
|
166
165
|
when 'title', 'reftext'
|
167
166
|
@attributes[name] = value
|
@@ -173,33 +172,26 @@ class AttributeList
|
|
173
172
|
end
|
174
173
|
end
|
175
174
|
else
|
176
|
-
|
177
|
-
if (positional_attr_name = positional_attrs[index])
|
178
|
-
@attributes[positional_attr_name] =
|
175
|
+
name = @block.apply_subs name if single_quoted && @block
|
176
|
+
if (positional_attr_name = positional_attrs[index]) && name
|
177
|
+
@attributes[positional_attr_name] = name
|
179
178
|
end
|
180
|
-
# QUESTION should we
|
181
|
-
@attributes[index + 1] =
|
182
|
-
# QUESTION should we assign the resolved name as an attribute?
|
183
|
-
#@attributes[resolved_name] = nil
|
179
|
+
# QUESTION should we assign the positional key even when it's claimed by a positional attribute?
|
180
|
+
@attributes[index + 1] = name
|
184
181
|
end
|
185
182
|
|
186
|
-
|
183
|
+
continue
|
187
184
|
end
|
188
185
|
|
189
186
|
def parse_attribute_value quote
|
190
187
|
# empty quoted value
|
191
|
-
if @scanner.peek
|
188
|
+
if (@scanner.peek 1) == quote
|
192
189
|
@scanner.get_byte
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
if (value = scan_to_quote quote)
|
190
|
+
''
|
191
|
+
elsif (value = scan_to_quote quote)
|
197
192
|
@scanner.get_byte
|
198
|
-
|
199
|
-
|
200
|
-
else
|
201
|
-
value
|
202
|
-
end
|
193
|
+
(value.include? BACKSLASH) ? (value.gsub EscapedQuotes[quote], quote) : value
|
194
|
+
# leading quote only
|
203
195
|
else
|
204
196
|
%(#{quote}#{scan_to_delimiter})
|
205
197
|
end
|
@@ -222,7 +214,7 @@ class AttributeList
|
|
222
214
|
end
|
223
215
|
|
224
216
|
def scan_to_quote quote
|
225
|
-
@scanner.scan
|
217
|
+
@scanner.scan BoundaryRx[quote]
|
226
218
|
end
|
227
219
|
end
|
228
220
|
end
|
@@ -42,6 +42,8 @@ module Asciidoctor
|
|
42
42
|
non_posix_env = ::File::ALT_SEPARATOR == RS
|
43
43
|
err = @err || $stderr
|
44
44
|
show_timings = false
|
45
|
+
# NOTE in Ruby 2.7, RubyGems sets SOURCE_DATE_EPOCH if it's not set
|
46
|
+
::ENV.delete 'SOURCE_DATE_EPOCH' if (::ENV.key? 'IGNORE_SOURCE_DATE_EPOCH') && (::Gem.respond_to? :source_date_epoch)
|
45
47
|
|
46
48
|
@options.map do |key, val|
|
47
49
|
case key
|
@@ -39,14 +39,15 @@ module Asciidoctor
|
|
39
39
|
# NOTE don't use squiggly heredoc to maintain compatibility with Ruby < 2.3
|
40
40
|
opts.banner = <<-'EOS'.gsub ' ', ''
|
41
41
|
Usage: asciidoctor [OPTION]... FILE...
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
Convert the AsciiDoc input FILE(s) to the backend output format (e.g., HTML 5, DocBook 5, etc.)
|
43
|
+
Unless specified otherwise, the output is written to a file whose name is derived from the input file.
|
44
|
+
Application log messages are printed to STDERR.
|
45
|
+
Example: asciidoctor input.adoc
|
45
46
|
|
46
47
|
EOS
|
47
48
|
|
48
|
-
opts.on('-b', '--backend BACKEND', 'set output format
|
49
|
-
'additional backends are supported via
|
49
|
+
opts.on('-b', '--backend BACKEND', 'set backend output format: [html5, xhtml5, docbook5, manpage] (default: html5)',
|
50
|
+
'additional backends are supported via extended converters (e.g., pdf, epub3)') do |backend|
|
50
51
|
self[:attributes]['backend'] = backend
|
51
52
|
end
|
52
53
|
opts.on('-d', '--doctype DOCTYPE', ['article', 'book', 'manpage', 'inline'],
|
@@ -76,8 +77,8 @@ module Asciidoctor
|
|
76
77
|
opts.on('-n', '--section-numbers', 'auto-number section titles in the HTML backend; disabled by default') do
|
77
78
|
self[:attributes]['sectnums'] = ''
|
78
79
|
end
|
79
|
-
opts.on('--eruby ERUBY', ['erb', 'erubis'],
|
80
|
-
'specify eRuby implementation to use when rendering custom ERB templates: [erb, erubis] (default: erb)') do |eruby|
|
80
|
+
opts.on('--eruby ERUBY', ['erb', 'erubi', 'erubis'],
|
81
|
+
'specify eRuby implementation to use when rendering custom ERB templates: [erb, erubi, erubis] (default: erb)') do |eruby|
|
81
82
|
self[:eruby] = eruby
|
82
83
|
end
|
83
84
|
opts.on('-a', '--attribute name[=value]', 'a document attribute to set in the form of name, name!, or name=value pair',
|
@@ -128,7 +129,7 @@ module Asciidoctor
|
|
128
129
|
opts.on('--trace', 'include backtrace information when reporting errors (default: false)') do |trace|
|
129
130
|
self[:trace] = true
|
130
131
|
end
|
131
|
-
opts.on('-v', '--verbose', '
|
132
|
+
opts.on('-v', '--verbose', 'directs application messages logged at DEBUG or INFO level to STDERR (default: false)') do |verbose|
|
132
133
|
self[:verbose] = 2
|
133
134
|
end
|
134
135
|
opts.on('-w', '--warnings', 'turn on script warnings (default: false)') do |warnings|
|
@@ -205,7 +206,7 @@ module Asciidoctor
|
|
205
206
|
# shave off the file to process so that options errors appear correctly
|
206
207
|
if args.size == 1 && args[0] == '-'
|
207
208
|
infiles << args.pop
|
208
|
-
|
209
|
+
else
|
209
210
|
args.each do |file|
|
210
211
|
if file.start_with? '-'
|
211
212
|
# warn, but don't panic; we may have enough to proceed, so we won't force a failure
|