asciidoctor 2.0.16 → 2.0.18

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.
@@ -74,10 +74,10 @@ code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;
74
74
  ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
75
75
  ul,ol{margin-left:1.5em}
76
76
  ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
77
- ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
78
- ul.square{list-style-type:square}
79
77
  ul.circle{list-style-type:circle}
80
78
  ul.disc{list-style-type:disc}
79
+ ul.square{list-style-type:square}
80
+ ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
81
81
  ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
82
82
  dl dt{margin-bottom:.3125em;font-weight:bold}
83
83
  dl dd{margin-bottom:1.25em}
@@ -183,7 +183,8 @@ body.toc2.toc-right{padding-left:0;padding-right:20em}}
183
183
  #content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
184
184
  details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
185
185
  details{margin-left:1.25rem}
186
- details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;-webkit-tap-highlight-color:transparent}
186
+ details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
187
+ details>summary::-webkit-details-marker{display:none}
187
188
  details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
188
189
  details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
189
190
  details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
@@ -225,9 +226,8 @@ pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
225
226
  table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
226
227
  table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
227
228
  table.linenotable td.code{padding-left:.75em}
228
- table.linenotable td.linenos{border-right:1px solid;opacity:.35;padding-right:.5em}
229
- pre.pygments .lineno{border-right:1px solid;opacity:.35;display:inline-block;margin-right:.75em}
230
- pre.pygments .lineno::before{content:"";margin-right:-.125em}
229
+ table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
230
+ pre.pygments span.linenos{display:inline-block;margin-right:.75em}
231
231
  .quoteblock{margin:0 1em 1.25em 1.5em;display:table}
232
232
  .quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
233
233
  .quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
@@ -264,7 +264,7 @@ table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-c
264
264
  table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
265
265
  table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
266
266
  table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
267
- table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd),table.stripes-even tr:nth-of-type(even),table.stripes-hover tr:hover{background:#f8f8f7}
267
+ table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
268
268
  th.halign-left,td.halign-left{text-align:left}
269
269
  th.halign-right,td.halign-right{text-align:right}
270
270
  th.halign-center,td.halign-center{text-align:center}
@@ -280,10 +280,11 @@ ol{margin-left:1.75em}
280
280
  ul li ol{margin-left:1.5em}
281
281
  dl dd{margin-left:1.125em}
282
282
  dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
283
- ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
283
+ li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
284
284
  ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
285
285
  ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
286
286
  ul.unstyled,ol.unstyled{margin-left:0}
287
+ li>p:empty:only-child::before{content:"";display:inline-block}
287
288
  ul.checklist>li>p:first-child{margin-left:-1em}
288
289
  ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
289
290
  ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
@@ -326,8 +327,6 @@ sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
326
327
  #footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
327
328
  #footnotes .footnote:last-of-type{margin-bottom:0}
328
329
  #content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
329
- .gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
330
- .gist .file-data>table td.line-data{width:99%}
331
330
  div.unbreakable{page-break-inside:avoid}
332
331
  .big{font-size:larger}
333
332
  .small{font-size:smaller}
@@ -1,15 +1,15 @@
1
- /* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
1
+ /*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
2
2
  pre.CodeRay{background:#f7f7f8}
3
- .CodeRay .line-numbers{border-right:1px solid currentColor;opacity:.35;padding:0 .5em 0 0}
3
+ .CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
4
4
  .CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
5
5
  .CodeRay .line-numbers strong{color:#000}
6
6
  table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
7
7
  table.CodeRay td{vertical-align:top;line-height:inherit}
8
8
  table.CodeRay td.line-numbers{text-align:right}
9
9
  table.CodeRay td.code{padding:0 0 0 .75em}
10
- .CodeRay .debug{color:#fff !important;background:#000080 !important}
10
+ .CodeRay .debug{color:#fff!important;background:navy!important}
11
11
  .CodeRay .annotation{color:#007}
12
- .CodeRay .attribute-name{color:#000080}
12
+ .CodeRay .attribute-name{color:navy}
13
13
  .CodeRay .attribute-value{color:#700}
14
14
  .CodeRay .binary{color:#509}
15
15
  .CodeRay .comment{color:#998;font-style:italic}
@@ -18,7 +18,7 @@ table.CodeRay td.code{padding:0 0 0 .75em}
18
18
  .CodeRay .char .delimiter{color:#039}
19
19
  .CodeRay .class{color:#458;font-weight:bold}
20
20
  .CodeRay .complex{color:#a08}
21
- .CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
21
+ .CodeRay .constant,.CodeRay .predefined-constant{color:teal}
22
22
  .CodeRay .color{color:#099}
23
23
  .CodeRay .class-variable{color:#369}
24
24
  .CodeRay .decorator{color:#b0b}
@@ -33,7 +33,7 @@ table.CodeRay td.code{padding:0 0 0 .75em}
33
33
  .CodeRay .exception{color:inherit}
34
34
  .CodeRay .filename{color:#099}
35
35
  .CodeRay .function{color:#900;font-weight:bold}
36
- .CodeRay .global-variable{color:#008080}
36
+ .CodeRay .global-variable{color:teal}
37
37
  .CodeRay .hex{color:#058}
38
38
  .CodeRay .integer,.CodeRay .float{color:#099}
39
39
  .CodeRay .include{color:#555}
@@ -44,7 +44,7 @@ table.CodeRay td.code{padding:0 0 0 .75em}
44
44
  .CodeRay .inline-delimiter{color:#d14}
45
45
  .CodeRay .important{color:#555;font-weight:bold}
46
46
  .CodeRay .interpreted{color:#b2b}
47
- .CodeRay .instance-variable{color:#008080}
47
+ .CodeRay .instance-variable{color:teal}
48
48
  .CodeRay .label{color:#970}
49
49
  .CodeRay .local-variable{color:#963}
50
50
  .CodeRay .octal{color:#40e}
@@ -54,7 +54,7 @@ table.CodeRay td.code{padding:0 0 0 .75em}
54
54
  .CodeRay .directive{font-weight:bold}
55
55
  .CodeRay .type{font-weight:bold}
56
56
  .CodeRay .predefined-type{color:inherit}
57
- .CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
57
+ .CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
58
58
  .CodeRay .key{color:#808}
59
59
  .CodeRay .key .delimiter{color:#606}
60
60
  .CodeRay .key .char{color:#80f}
@@ -74,7 +74,7 @@ table.CodeRay td.code{padding:0 0 0 .75em}
74
74
  .CodeRay .symbol{color:#990073}
75
75
  .CodeRay .symbol .content{color:#a60}
76
76
  .CodeRay .symbol .delimiter{color:#630}
77
- .CodeRay .tag{color:#008080}
77
+ .CodeRay .tag{color:teal}
78
78
  .CodeRay .tag-special{color:#d70}
79
79
  .CodeRay .variable{color:#036}
80
80
  .CodeRay .insert{background:#afa}
@@ -11,7 +11,7 @@ class AbstractBlock < AbstractNode
11
11
  # * :compound - this block contains other blocks
12
12
  # * :simple - this block holds a paragraph of prose that receives normal substitutions
13
13
  # * :verbatim - this block holds verbatim text (displayed "as is") that receives verbatim substitutions
14
- # * :raw - this block holds unprocessed content passed directly to the output with no sustitutions applied
14
+ # * :raw - this block holds unprocessed content passed directly to the output with no substitutions applied
15
15
  # * :empty - this block has no content
16
16
  attr_accessor :content_model
17
17
 
@@ -129,11 +129,13 @@ class AbstractBlock < AbstractNode
129
129
 
130
130
  # Public: Check whether this block has any child Section objects.
131
131
  #
132
- # Only applies to Document and Section instances
132
+ # Acts an an abstract method that always returns false unless this block is an
133
+ # instance of Document or Section.
134
+ # Both Document and Section provide overrides for this method.
133
135
  #
134
- # Returns A [Boolean] to indicate whether this block has child Section objects
136
+ # Returns false
135
137
  def sections?
136
- @next_section_index > 0
138
+ false
137
139
  end
138
140
 
139
141
  # Deprecated: Legacy property to get the String or Integer numeral of this section.
@@ -269,7 +271,7 @@ class AbstractBlock < AbstractNode
269
271
  ORDERED_LIST_KEYWORDS[list_type || @style]
270
272
  end
271
273
 
272
- # Public: Get the String title of this Block with title substitions applied
274
+ # Public: Get the String title of this Block with title substitutions applied
273
275
  #
274
276
  # The following substitutions are applied to block and section titles:
275
277
  #
@@ -123,7 +123,7 @@ class Block < AbstractBlock
123
123
  result.join LF
124
124
  end
125
125
  else
126
- logger.warn %(Unknown content model '#{@content_model}' for block: #{self}) unless @content_model == :empty
126
+ logger.warn %(unknown content model '#{@content_model}' for block: #{self}) unless @content_model == :empty
127
127
  nil
128
128
  end
129
129
  end
@@ -19,7 +19,7 @@ module Asciidoctor
19
19
  when Options
20
20
  @options = first_option
21
21
  when ::Hash
22
- @options = Options.new options
22
+ @options = Options.new first_option
23
23
  else
24
24
  if ::Integer === (result = Options.parse! options)
25
25
  @code = result
@@ -142,7 +142,7 @@ module Asciidoctor
142
142
  raise e
143
143
  else
144
144
  err.puts ::RuntimeError === e ? %(#{e.message} (#{e.class})) : e.message
145
- err.puts ' Use --trace for backtrace'
145
+ err.puts ' Use --trace to show backtrace'
146
146
  end
147
147
  end
148
148
  nil
@@ -85,7 +85,11 @@ module Asciidoctor
85
85
  'this attribute takes precedence over the same attribute defined in the source document',
86
86
  'unless either the name or value ends in @ (i.e., name@=value or name=value@)') do |attr|
87
87
  next if (attr = attr.rstrip).empty? || attr == '='
88
- attr = attr.encode UTF_8 unless attr.encoding == UTF_8
88
+ begin
89
+ attr = attr.encode UTF_8
90
+ rescue ::EncodingError
91
+ attr = attr.force_encoding UTF_8
92
+ end unless attr.encoding == UTF_8
89
93
  name, _, val = attr.partition '='
90
94
  self[:attributes][name] = val
91
95
  end
@@ -119,7 +123,7 @@ module Asciidoctor
119
123
  'may be specified more than once') do |path|
120
124
  (self[:requires] ||= []).concat(path.split ',')
121
125
  end
122
- opts.on('--failure-level LEVEL', %w(warning WARNING error ERROR info INFO), 'set minimum logging level that triggers non-zero exit code: [WARN, ERROR, INFO] (default: FATAL)') do |level|
126
+ opts.on('--failure-level LEVEL', %w(info INFO warning WARNING error ERROR fatal FATAL), 'set minimum log level that yields a non-zero exit code: [INFO, WARN, ERROR, FATAL] (default: FATAL)') do |level|
123
127
  level = 'WARN' if (level = level.upcase) == 'WARNING'
124
128
  self[:failure_level] = ::Logger::Severity.const_get level
125
129
  end
@@ -258,7 +262,7 @@ module Asciidoctor
258
262
  raise $! if self[:trace]
259
263
  $stderr.puts 'asciidoctor: FAILED: \'tilt\' could not be loaded'
260
264
  $stderr.puts ' You must have the tilt gem installed (gem install tilt) to use custom backend templates'
261
- $stderr.puts ' Use --trace for backtrace'
265
+ $stderr.puts ' Use --trace to show backtrace'
262
266
  return 1
263
267
  rescue ::SystemExit
264
268
  # not permitted here
@@ -278,7 +282,7 @@ module Asciidoctor
278
282
  rescue ::LoadError
279
283
  raise $! if self[:trace]
280
284
  $stderr.puts %(asciidoctor: FAILED: '#{path}' could not be loaded)
281
- $stderr.puts ' Use --trace for backtrace'
285
+ $stderr.puts ' Use --trace to show backtrace'
282
286
  return 1
283
287
  rescue ::SystemExit
284
288
  # not permitted here
@@ -626,16 +626,18 @@ Your browser does not support the audio tag.
626
626
  target = node.attr 'target'
627
627
  width_attr = (node.attr? 'width') ? %( width="#{node.attr 'width'}") : ''
628
628
  height_attr = (node.attr? 'height') ? %( height="#{node.attr 'height'}") : ''
629
- if ((node.attr? 'format', 'svg') || (target.include? '.svg')) && node.document.safe < SafeMode::SECURE &&
630
- ((svg = (node.option? 'inline')) || (obj = (node.option? 'interactive')))
631
- if svg
629
+ if ((node.attr? 'format', 'svg') || (target.include? '.svg')) && node.document.safe < SafeMode::SECURE
630
+ if node.option? 'inline'
632
631
  img = (read_svg_contents node, target) || %(<span class="alt">#{node.alt}</span>)
633
- elsif obj
634
- fallback = (node.attr? 'fallback') ? %(<img src="#{node.image_uri(node.attr 'fallback')}" alt="#{encode_attribute_value node.alt}"#{width_attr}#{height_attr}#{@void_element_slash}>) : %(<span class="alt">#{node.alt}</span>)
632
+ elsif node.option? 'interactive'
633
+ fallback = (node.attr? 'fallback') ? %(<img src="#{node.image_uri node.attr 'fallback'}" alt="#{encode_attribute_value node.alt}"#{width_attr}#{height_attr}#{@void_element_slash}>) : %(<span class="alt">#{node.alt}</span>)
635
634
  img = %(<object type="image/svg+xml" data="#{node.image_uri target}"#{width_attr}#{height_attr}>#{fallback}</object>)
635
+ else
636
+ img = %(<img src="#{node.image_uri target}" alt="#{encode_attribute_value node.alt}"#{width_attr}#{height_attr}#{@void_element_slash}>)
636
637
  end
638
+ else
639
+ img = %(<img src="#{node.image_uri target}" alt="#{encode_attribute_value node.alt}"#{width_attr}#{height_attr}#{@void_element_slash}>)
637
640
  end
638
- img ||= %(<img src="#{node.image_uri target}" alt="#{encode_attribute_value node.alt}"#{width_attr}#{height_attr}#{@void_element_slash}>)
639
641
  img = %(<a class="image" href="#{node.attr 'link'}"#{(append_link_constraint_attrs node).join}>#{img}</a>) if node.attr? 'link'
640
642
  id_attr = node.id ? %( id="#{node.id}") : ''
641
643
  classes = ['imageblock']
@@ -859,20 +861,19 @@ Your browser does not support the audio tag.
859
861
  if (stripes = node.attr 'stripes', nil, 'table-stripes')
860
862
  classes << %(stripes-#{stripes})
861
863
  end
862
- styles = []
864
+ style_attribute = ''
863
865
  if (autowidth = node.option? 'autowidth') && !(node.attr? 'width')
864
866
  classes << 'fit-content'
865
867
  elsif (tablewidth = node.attr 'tablepcwidth') == 100
866
868
  classes << 'stretch'
867
869
  else
868
- styles << %(width: #{tablewidth}%;)
870
+ style_attribute = %( style="width: #{tablewidth}%;")
869
871
  end
870
872
  classes << (node.attr 'float') if node.attr? 'float'
871
873
  if (role = node.role)
872
874
  classes << role
873
875
  end
874
876
  class_attribute = %( class="#{classes.join ' '}")
875
- style_attribute = styles.empty? ? '' : %( style="#{styles.join ' '}")
876
877
 
877
878
  result << %(<table#{id_attribute}#{class_attribute}#{style_attribute}>)
878
879
  result << %(<caption class="title">#{node.captioned_title}</caption>) if node.title?
@@ -1035,12 +1036,14 @@ Your browser does not support the audio tag.
1035
1036
  end
1036
1037
  start_anchor = (node.attr? 'start') ? %(#at=#{node.attr 'start'}) : ''
1037
1038
  delimiter = ['?']
1039
+ target, hash = (node.attr 'target').split '/', 2
1040
+ hash_param = (hash ||= node.attr 'hash') ? %(#{delimiter.pop || '&amp;'}h=#{hash}) : ''
1038
1041
  autoplay_param = (node.option? 'autoplay') ? %(#{delimiter.pop || '&amp;'}autoplay=1) : ''
1039
1042
  loop_param = (node.option? 'loop') ? %(#{delimiter.pop || '&amp;'}loop=1) : ''
1040
1043
  muted_param = (node.option? 'muted') ? %(#{delimiter.pop || '&amp;'}muted=1) : ''
1041
1044
  %(<div#{id_attribute}#{class_attribute}>#{title_element}
1042
1045
  <div class="content">
1043
- <iframe#{width_attribute}#{height_attribute} src="#{asset_uri_scheme}//player.vimeo.com/video/#{node.attr 'target'}#{autoplay_param}#{loop_param}#{muted_param}#{start_anchor}" frameborder="0"#{(node.option? 'nofullscreen') ? '' : (append_boolean_attribute 'allowfullscreen', xml)}></iframe>
1046
+ <iframe#{width_attribute}#{height_attribute} src="#{asset_uri_scheme}//player.vimeo.com/video/#{target}#{hash_param}#{autoplay_param}#{loop_param}#{muted_param}#{start_anchor}" frameborder="0"#{(node.option? 'nofullscreen') ? '' : (append_boolean_attribute 'allowfullscreen', xml)}></iframe>
1044
1047
  </div>
1045
1048
  </div>)
1046
1049
  when 'youtube'
@@ -1076,7 +1079,7 @@ Your browser does not support the audio tag.
1076
1079
  target, playlist = target.split ',', 2
1077
1080
  if (playlist ||= (node.attr 'playlist'))
1078
1081
  # INFO playlist bar doesn't appear in Firefox unless showinfo=1 and modestbranding=1
1079
- list_param = %(&amp;playlist=#{playlist})
1082
+ list_param = %(&amp;playlist=#{target},#{playlist})
1080
1083
  else
1081
1084
  # NOTE for loop to work, playlist must be specified; use VIDEO_ID if there's no explicit playlist
1082
1085
  list_param = has_loop_param ? %(&amp;playlist=#{target}) : ''
@@ -1180,44 +1183,49 @@ Your browser does not support the video tag.
1180
1183
  end
1181
1184
 
1182
1185
  def convert_inline_image node
1183
- if (type = node.type || 'image') == 'icon' && (node.document.attr? 'icons', 'font')
1184
- class_attr_val = %(fa fa-#{node.target})
1185
- { 'size' => 'fa-', 'rotate' => 'fa-rotate-', 'flip' => 'fa-flip-' }.each do |key, prefix|
1186
- class_attr_val = %(#{class_attr_val} #{prefix}#{node.attr key}) if node.attr? key
1186
+ target = node.target
1187
+ if (type = node.type || 'image') == 'icon'
1188
+ if (icons = node.document.attr 'icons') == 'font'
1189
+ i_class_attr_val = %(fa fa-#{target})
1190
+ i_class_attr_val = %(#{i_class_attr_val} fa-#{node.attr 'size'}) if node.attr? 'size'
1191
+ if node.attr? 'flip'
1192
+ i_class_attr_val = %(#{i_class_attr_val} fa-flip-#{node.attr 'flip'})
1193
+ elsif node.attr? 'rotate'
1194
+ i_class_attr_val = %(#{i_class_attr_val} fa-rotate-#{node.attr 'rotate'})
1195
+ end
1196
+ attrs = (node.attr? 'title') ? %( title="#{node.attr 'title'}") : ''
1197
+ img = %(<i class="#{i_class_attr_val}"#{attrs}></i>)
1198
+ elsif icons
1199
+ attrs = (node.attr? 'width') ? %( width="#{node.attr 'width'}") : ''
1200
+ attrs = %(#{attrs} height="#{node.attr 'height'}") if node.attr? 'height'
1201
+ attrs = %(#{attrs} title="#{node.attr 'title'}") if node.attr? 'title'
1202
+ img = %(<img src="#{node.icon_uri target}" alt="#{encode_attribute_value node.alt}"#{attrs}#{@void_element_slash}>)
1203
+ else
1204
+ img = %([#{node.alt}&#93;)
1187
1205
  end
1188
- title_attr = (node.attr? 'title') ? %( title="#{node.attr 'title'}") : ''
1189
- img = %(<i class="#{class_attr_val}"#{title_attr}></i>)
1190
- elsif type == 'icon' && !(node.document.attr? 'icons')
1191
- img = %([#{node.alt}])
1192
1206
  else
1193
- target = node.target
1194
- attrs = []
1195
- attrs << %( width="#{node.attr 'width'}") if node.attr? 'width'
1196
- attrs << %( height="#{node.attr 'height'}") if node.attr? 'height'
1197
- attrs << %( title="#{node.attr 'title'}") if node.attr? 'title'
1198
- attrs = attrs.empty? ? '' : attrs.join
1199
- if type != 'icon' && ((node.attr? 'format', 'svg') || (target.include? '.svg')) &&
1200
- node.document.safe < SafeMode::SECURE && ((svg = (node.option? 'inline')) || (obj = (node.option? 'interactive')))
1201
- if svg
1207
+ attrs = (node.attr? 'width') ? %( width="#{node.attr 'width'}") : ''
1208
+ attrs = %(#{attrs} height="#{node.attr 'height'}") if node.attr? 'height'
1209
+ attrs = %(#{attrs} title="#{node.attr 'title'}") if node.attr? 'title'
1210
+ if ((node.attr? 'format', 'svg') || (target.include? '.svg')) && node.document.safe < SafeMode::SECURE
1211
+ if node.option? 'inline'
1202
1212
  img = (read_svg_contents node, target) || %(<span class="alt">#{node.alt}</span>)
1203
- elsif obj
1204
- fallback = (node.attr? 'fallback') ? %(<img src="#{node.image_uri(node.attr 'fallback')}" alt="#{encode_attribute_value node.alt}"#{attrs}#{@void_element_slash}>) : %(<span class="alt">#{node.alt}</span>)
1213
+ elsif node.option? 'interactive'
1214
+ fallback = (node.attr? 'fallback') ? %(<img src="#{node.image_uri node.attr 'fallback'}" alt="#{encode_attribute_value node.alt}"#{attrs}#{@void_element_slash}>) : %(<span class="alt">#{node.alt}</span>)
1205
1215
  img = %(<object type="image/svg+xml" data="#{node.image_uri target}"#{attrs}>#{fallback}</object>)
1216
+ else
1217
+ img = %(<img src="#{node.image_uri target}" alt="#{encode_attribute_value node.alt}"#{attrs}#{@void_element_slash}>)
1206
1218
  end
1219
+ else
1220
+ img = %(<img src="#{node.image_uri target}" alt="#{encode_attribute_value node.alt}"#{attrs}#{@void_element_slash}>)
1207
1221
  end
1208
- img ||= %(<img src="#{type == 'icon' ? (node.icon_uri target) : (node.image_uri target)}" alt="#{encode_attribute_value node.alt}"#{attrs}#{@void_element_slash}>)
1209
1222
  end
1210
1223
  img = %(<a class="image" href="#{node.attr 'link'}"#{(append_link_constraint_attrs node).join}>#{img}</a>) if node.attr? 'link'
1224
+ class_attr_val = type
1211
1225
  if (role = node.role)
1212
- if node.attr? 'float'
1213
- class_attr_val = %(#{type} #{node.attr 'float'} #{role})
1214
- else
1215
- class_attr_val = %(#{type} #{role})
1216
- end
1226
+ class_attr_val = (node.attr? 'float') ? %(#{class_attr_val} #{node.attr 'float'} #{role}) : %(#{class_attr_val} #{role})
1217
1227
  elsif node.attr? 'float'
1218
- class_attr_val = %(#{type} #{node.attr 'float'})
1219
- else
1220
- class_attr_val = type
1228
+ class_attr_val = %(#{class_attr_val} #{node.attr 'float'})
1221
1229
  end
1222
1230
  %(<span class="#{class_attr_val}">#{img}</span>)
1223
1231
  end
@@ -196,7 +196,7 @@ class Converter::TemplateConverter < Converter::Base
196
196
  def scan_dir template_dir, pattern, template_cache = nil
197
197
  result, helpers = {}, nil
198
198
  # Grab the files in the top level of the directory (do not recurse)
199
- ::Dir.glob(pattern).select {|match| ::File.file? match }.each do |file|
199
+ ::Dir.glob(pattern).keep_if {|match| ::File.file? match }.each do |file|
200
200
  if (basename = ::File.basename file) == 'helpers.rb'
201
201
  helpers = file
202
202
  next
@@ -42,7 +42,7 @@ module Asciidoctor
42
42
  # puts Asciidoctor.convert_file 'sample.adoc', safe: :safe
43
43
  module Converter
44
44
  autoload :CompositeConverter, %(#{__dir__}/converter/composite)
45
- autoload :TemplateConverter, %(#{__dir__}/converter/template)
45
+ autoload :TemplateConverter, %(#{__dir__}/converter/template) unless RUBY_ENGINE == 'opal'
46
46
 
47
47
  # Public: The String backend name that this converter is handling.
48
48
  attr_reader :backend
@@ -3,6 +3,6 @@
3
3
  # NOTE use `send :prepend` to be nice to Ruby 2.0
4
4
  Hash.send :prepend, (Module.new do
5
5
  def merge *args
6
- (len = args.length) < 1 ? super({}) : (len > 1 ? args.inject(self) {|acc, arg| acc.merge arg } : (super args[0]))
6
+ (len = args.length) < 1 ? dup : (len > 1 ? args.inject(self) {|acc, arg| acc.merge arg } : (super args[0]))
7
7
  end
8
8
  end) if (Hash.instance_method :merge).arity == 1
@@ -198,7 +198,7 @@ class Document < AbstractBlock
198
198
  # Public: Get the document catalog Hash
199
199
  attr_reader :catalog
200
200
 
201
- # Public: Alias catalog property as references for backwards compatiblity
201
+ # Public: Alias catalog property as references for backwards compatibility
202
202
  alias references catalog
203
203
 
204
204
  # Public: Get the Hash of document counters
@@ -257,6 +257,7 @@ class Document < AbstractBlock
257
257
  @parent_document = parent_doc
258
258
  options[:base_dir] ||= parent_doc.base_dir
259
259
  options[:catalog_assets] = true if parent_doc.options[:catalog_assets]
260
+ options[:to_dir] = parent_doc.options[:to_dir] if parent_doc.options[:to_dir]
260
261
  @catalog = parent_doc.catalog.merge footnotes: []
261
262
  # QUESTION should we support setting attribute in parent document from nested document?
262
263
  @attribute_overrides = attr_overrides = (parent_doc.instance_variable_get :@attribute_overrides).merge parent_doc.attributes
@@ -328,7 +329,7 @@ class Document < AbstractBlock
328
329
  @timings = options.delete :timings
329
330
  @path_resolver = PathResolver.new
330
331
  initialize_extensions = (defined? ::Asciidoctor::Extensions) || (options.key? :extensions) ? ::Asciidoctor::Extensions : nil
331
- @extensions = nil # initialize furthur down if initialize_extensions is true
332
+ @extensions = nil # initialize further down if initialize_extensions is true
332
333
  options[:standalone] = options[:header_footer] if (options.key? :header_footer) && !(options.key? :standalone)
333
334
  end
334
335
 
@@ -631,6 +632,13 @@ class Document < AbstractBlock
631
632
  end
632
633
  end
633
634
 
635
+ # Public: Check whether this Document has any child Section objects.
636
+ #
637
+ # Returns A [Boolean] to indicate whether this Document has child Section objects
638
+ def sections?
639
+ @next_section_index > 0
640
+ end
641
+
634
642
  def footnotes?
635
643
  @catalog[:footnotes].empty? ? false : true
636
644
  end
@@ -965,8 +973,14 @@ class Document < AbstractBlock
965
973
 
966
974
  # Public: Write the output to the specified file
967
975
  #
968
- # If the converter responds to :write, delegate the work of writing the file
969
- # to that method. Otherwise, write the output the specified file.
976
+ # If the converter responds to :write, delegate the work of writing the output
977
+ # to that method. Otherwise, write the output to the specified file. In the
978
+ # latter case, this method ensures the output has a trailing newline if the
979
+ # target responds to write and the output is not empty.
980
+ #
981
+ # output - The output to write. Unless the converter responds to write, this
982
+ # object is expected to be a String.
983
+ # target - The file to write, either a File object or a String path.
970
984
  #
971
985
  # Returns nothing
972
986
  def write output, target
@@ -511,6 +511,15 @@ module Extensions
511
511
  # registered to handle this name and, if found, invokes its {Processor#process}
512
512
  # method to build a corresponding node in the document tree.
513
513
  #
514
+ # If the process method returns an instance of Block, the content model of that
515
+ # Block is :compound, and the Block contains at least one line, the parser will
516
+ # parse those lines into blocks and append them to the returned block.
517
+ #
518
+ # If your custom block can be applied to a paragraph or delimited block, and you
519
+ # want to preserve the content model of the input, check whether the value of
520
+ # the cloaked-context attribute is :paragraph. If it is, set the content model of
521
+ # the returned block to :simple. Otherwise, set the content model to :compound.
522
+ #
514
523
  # AsciiDoc example:
515
524
  #
516
525
  # [shout]
@@ -594,6 +603,10 @@ module Extensions
594
603
  # Public: BlockMacroProcessors are used to handle block macros that have a
595
604
  # custom name.
596
605
  #
606
+ # If the process method returns an instance of Block, the content model of that
607
+ # Block is :compound, and the Block contains at least one line, the parser will
608
+ # parse those lines into blocks an assigned them to the returned block.
609
+ #
597
610
  # BlockMacroProcessor implementations must extend BlockMacroProcessor.
598
611
  class BlockMacroProcessor < MacroProcessor
599
612
  def name
@@ -666,7 +679,7 @@ module Extensions
666
679
 
667
680
  # Public: A specialization of the Extension proxy that additionally stores a
668
681
  # reference to the {Processor#process} method. By storing this reference, its
669
- # possible to accomodate both concrete extension implementations and Procs.
682
+ # possible to accommodate both concrete extension implementations and Procs.
670
683
  class ProcessorExtension < Extension
671
684
  attr_reader :process_method
672
685
 
@@ -708,6 +721,7 @@ module Extensions
708
721
 
709
722
  def initialize groups = {}
710
723
  @groups = groups
724
+ reset
711
725
  @preprocessor_extensions = @tree_processor_extensions = @postprocessor_extensions = @include_processor_extensions = @docinfo_processor_extensions = @block_extensions = @block_macro_extensions = @inline_macro_extensions = nil
712
726
  @document = nil
713
727
  end
@@ -719,6 +733,7 @@ module Extensions
719
733
  #
720
734
  # Returns the instance of this [Registry].
721
735
  def activate document
736
+ reset if @document
722
737
  @document = document
723
738
  unless (ext_groups = Extensions.groups.values + @groups.values).empty?
724
739
  ext_groups.each do |group|
@@ -954,7 +969,7 @@ module Extensions
954
969
  end
955
970
 
956
971
  # Public: Registers an {DocinfoProcessor} with the extension registry to
957
- # add additionnal docinfo to the document.
972
+ # add additional docinfo to the document.
958
973
  #
959
974
  # The DocinfoProcessor may be one of four types:
960
975
  #
@@ -1337,7 +1352,7 @@ module Extensions
1337
1352
  yield processor
1338
1353
  end
1339
1354
  unless processor.process_block_given?
1340
- raise ::ArgumentError, %(No block specified to process #{kind_name} extension at #{block.source_location})
1355
+ raise ::NoMethodError, %(No block specified to process #{kind_name} extension at #{block.source_location.join ':'})
1341
1356
  end
1342
1357
  processor.freeze
1343
1358
  extension = ProcessorExtension.new kind, processor
@@ -1381,10 +1396,10 @@ module Extensions
1381
1396
  yield processor
1382
1397
  end
1383
1398
  unless (name = as_symbol processor.name)
1384
- raise ::ArgumentError, %(No name specified for #{kind_name} extension at #{block.source_location})
1399
+ raise ::ArgumentError, %(No name specified for #{kind_name} extension at #{block.source_location.join ':'})
1385
1400
  end
1386
1401
  unless processor.process_block_given?
1387
- raise ::NoMethodError, %(No block specified to process #{kind_name} extension at #{block.source_location})
1402
+ raise ::NoMethodError, %(No block specified to process #{kind_name} extension at #{block.source_location.join ':'})
1388
1403
  end
1389
1404
  processor.freeze
1390
1405
  kind_store[name] = ProcessorExtension.new kind, processor
@@ -1416,6 +1431,11 @@ module Extensions
1416
1431
  end
1417
1432
  end
1418
1433
 
1434
+ def reset
1435
+ @preprocessor_extensions = @tree_processor_extensions = @postprocessor_extensions = @include_processor_extensions = @docinfo_processor_extensions = @block_extensions = @block_macro_extensions = @inline_macro_extensions = nil
1436
+ @document = nil
1437
+ end
1438
+
1419
1439
  def resolve_args args, expect
1420
1440
  opts = ::Hash === args[-1] ? args.pop : {}
1421
1441
  return opts if expect == 1
@@ -1520,7 +1540,7 @@ module Extensions
1520
1540
  #
1521
1541
  # Returns nothing
1522
1542
  def unregister *names
1523
- names.each {|group| @groups.delete group.to_sym }
1543
+ names.each_with_object(groups) {|group, catalog| catalog.delete group.to_sym }
1524
1544
  nil
1525
1545
  end
1526
1546
  end