asciidoctor 1.5.7.1 → 1.5.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +95 -5
  3. data/Gemfile +23 -13
  4. data/README-de.adoc +482 -0
  5. data/README-fr.adoc +128 -119
  6. data/README-jp.adoc +2 -3
  7. data/README-zh_CN.adoc +2 -3
  8. data/README.adoc +131 -106
  9. data/asciidoctor.gemspec +9 -7
  10. data/data/locale/attributes-ar.adoc +1 -1
  11. data/data/locale/attributes-bg.adoc +1 -1
  12. data/data/locale/attributes-ca.adoc +1 -1
  13. data/data/locale/attributes-cs.adoc +1 -1
  14. data/data/locale/attributes-da.adoc +1 -1
  15. data/data/locale/attributes-de.adoc +1 -1
  16. data/data/locale/attributes-en.adoc +1 -1
  17. data/data/locale/attributes-es.adoc +1 -1
  18. data/data/locale/attributes-fa.adoc +1 -1
  19. data/data/locale/attributes-fi.adoc +1 -1
  20. data/data/locale/attributes-fr.adoc +1 -1
  21. data/data/locale/attributes-hu.adoc +1 -1
  22. data/data/locale/attributes-id.adoc +1 -1
  23. data/data/locale/attributes-it.adoc +1 -1
  24. data/data/locale/attributes-ja.adoc +1 -1
  25. data/data/locale/attributes-kr.adoc +1 -1
  26. data/data/locale/attributes-nb.adoc +1 -1
  27. data/data/locale/attributes-nl.adoc +1 -1
  28. data/data/locale/attributes-nn.adoc +1 -1
  29. data/data/locale/attributes-pl.adoc +1 -1
  30. data/data/locale/attributes-pt.adoc +1 -1
  31. data/data/locale/attributes-pt_BR.adoc +1 -1
  32. data/data/locale/attributes-ro.adoc +1 -1
  33. data/data/locale/attributes-ru.adoc +1 -1
  34. data/data/locale/attributes-sr.adoc +5 -4
  35. data/data/locale/attributes-sr_Latn.adoc +5 -4
  36. data/data/locale/attributes-sv.adoc +23 -0
  37. data/data/locale/attributes-tr.adoc +1 -1
  38. data/data/locale/attributes-uk.adoc +1 -1
  39. data/data/locale/attributes-zh_CN.adoc +1 -1
  40. data/data/locale/attributes-zh_TW.adoc +1 -1
  41. data/data/stylesheets/asciidoctor-default.css +23 -23
  42. data/lib/asciidoctor.rb +110 -104
  43. data/lib/asciidoctor/abstract_block.rb +55 -32
  44. data/lib/asciidoctor/abstract_node.rb +32 -17
  45. data/lib/asciidoctor/attribute_list.rb +8 -7
  46. data/lib/asciidoctor/block.rb +5 -7
  47. data/lib/asciidoctor/cli/options.rb +5 -9
  48. data/lib/asciidoctor/converter.rb +2 -2
  49. data/lib/asciidoctor/converter/docbook45.rb +7 -20
  50. data/lib/asciidoctor/converter/docbook5.rb +36 -37
  51. data/lib/asciidoctor/converter/factory.rb +10 -8
  52. data/lib/asciidoctor/converter/html5.rb +90 -65
  53. data/lib/asciidoctor/converter/manpage.rb +72 -62
  54. data/lib/asciidoctor/converter/template.rb +8 -6
  55. data/lib/asciidoctor/core_ext/1.8.7/concurrent/hash.rb +5 -0
  56. data/lib/asciidoctor/document.rb +62 -10
  57. data/lib/asciidoctor/extensions.rb +74 -16
  58. data/lib/asciidoctor/helpers.rb +11 -14
  59. data/lib/asciidoctor/list.rb +2 -2
  60. data/lib/asciidoctor/parser.rb +223 -195
  61. data/lib/asciidoctor/path_resolver.rb +15 -7
  62. data/lib/asciidoctor/reader.rb +65 -36
  63. data/lib/asciidoctor/section.rb +6 -4
  64. data/lib/asciidoctor/substitutors.rb +170 -149
  65. data/lib/asciidoctor/table.rb +16 -8
  66. data/lib/asciidoctor/version.rb +1 -1
  67. data/man/asciidoctor.1 +6 -5
  68. data/man/asciidoctor.adoc +3 -2
  69. data/test/api_test.rb +236 -0
  70. data/test/attribute_list_test.rb +242 -0
  71. data/test/attributes_test.rb +65 -52
  72. data/test/blocks_test.rb +408 -260
  73. data/test/converter_test.rb +7 -7
  74. data/test/document_test.rb +60 -54
  75. data/test/extensions_test.rb +218 -32
  76. data/test/fixtures/doctime-localtime.adoc +2 -0
  77. data/test/fixtures/section-a.adoc +4 -0
  78. data/test/fixtures/subs.adoc +0 -1
  79. data/test/invoker_test.rb +56 -18
  80. data/test/links_test.rb +105 -81
  81. data/test/lists_test.rb +636 -265
  82. data/test/logger_test.rb +1 -1
  83. data/test/manpage_test.rb +140 -3
  84. data/test/paragraphs_test.rb +42 -42
  85. data/test/parser_test.rb +63 -183
  86. data/test/paths_test.rb +21 -4
  87. data/test/preamble_test.rb +9 -9
  88. data/test/reader_test.rb +78 -28
  89. data/test/sections_test.rb +273 -151
  90. data/test/substitutions_test.rb +53 -19
  91. data/test/tables_test.rb +286 -163
  92. data/test/test_helper.rb +4 -3
  93. data/test/text_test.rb +65 -65
  94. metadata +16 -21
@@ -29,7 +29,7 @@ module Asciidoctor
29
29
  result << '</listitem>'
30
30
  end
31
31
  result << %(</orderedlist>)
32
- result * LF
32
+ result.join LF
33
33
  end
34
34
 
35
35
  def inline_anchor node
@@ -52,28 +52,15 @@ module Asciidoctor
52
52
  end
53
53
  end
54
54
 
55
- def author_tag doc, index = nil
56
- if index
57
- firstname_key = %(firstname_#{index})
58
- middlename_key = %(middlename_#{index})
59
- lastname_key = %(lastname_#{index})
60
- email_key = %(email_#{index})
61
- else
62
- firstname_key = 'firstname'
63
- middlename_key = 'middlename'
64
- lastname_key = 'lastname'
65
- email_key = 'email'
66
- end
67
-
55
+ def author_tag author
68
56
  result = []
69
57
  result << '<author>'
70
- result << %(<firstname>#{doc.attr firstname_key}</firstname>) if doc.attr? firstname_key
71
- result << %(<othername>#{doc.attr middlename_key}</othername>) if doc.attr? middlename_key
72
- result << %(<surname>#{doc.attr lastname_key}</surname>) if doc.attr? lastname_key
73
- result << %(<email>#{doc.attr email_key}</email>) if doc.attr? email_key
58
+ result << %(<firstname>#{author.firstname}</firstname>) if author.firstname
59
+ result << %(<othername>#{author.middlename}</othername>) if author.middlename
60
+ result << %(<surname>#{author.lastname}</surname>) if author.lastname
61
+ result << %(<email>#{author.email}</email>) if author.email
74
62
  result << '</author>'
75
-
76
- result * LF
63
+ result.join LF
77
64
  end
78
65
 
79
66
  def common_attributes id, role = nil, reftext = nil
@@ -38,8 +38,7 @@ module Asciidoctor
38
38
  result << footer_docinfo
39
39
  end
40
40
  result << %(</#{root_tag_name}>)
41
-
42
- result * LF
41
+ result.join LF
43
42
  end
44
43
 
45
44
  alias embedded content
@@ -77,7 +76,7 @@ module Asciidoctor
77
76
  result << '</callout>'
78
77
  end
79
78
  result << %(</calloutlist>)
80
- result * LF
79
+ result.join LF
81
80
  end
82
81
 
83
82
  (DLIST_TAGS = {
@@ -160,7 +159,7 @@ module Asciidoctor
160
159
  result << %(</#{list_tag}>) if list_tag
161
160
  end
162
161
 
163
- result * LF
162
+ result.join LF
164
163
  end
165
164
 
166
165
  def example node
@@ -221,9 +220,17 @@ module Asciidoctor
221
220
  def listing node
222
221
  informal = !node.title?
223
222
  listing_attributes = (common_attributes node.id, node.role, node.reftext)
224
- if node.style == 'source' && (node.attr? 'language')
225
- numbering = (node.attr? 'linenums', nil, false) ? 'numbered' : 'unnumbered'
226
- listing_content = %(<programlisting#{informal ? listing_attributes : ''} language="#{node.attr 'language', '', false}" linenumbering="#{numbering}">#{node.content}</programlisting>)
223
+ if node.style == 'source' && ((attrs = node.attributes).key? 'language')
224
+ if attrs.key? 'linenums'
225
+ if attrs.key? 'start'
226
+ numbering_attributes = %( linenumbering="numbered" startinglinenumber="#{attrs['start'].to_i}")
227
+ else
228
+ numbering_attributes = ' linenumbering="numbered"'
229
+ end
230
+ else
231
+ numbering_attributes = ' linenumbering="unnumbered"'
232
+ end
233
+ listing_content = %(<programlisting#{informal ? listing_attributes : ''} language="#{attrs['language']}"#{numbering_attributes}>#{node.content}</programlisting>)
227
234
  else
228
235
  listing_content = %(<screen#{informal ? listing_attributes : ''}>#{node.content}</screen>)
229
236
  end
@@ -298,7 +305,7 @@ module Asciidoctor
298
305
  result << '</listitem>'
299
306
  end
300
307
  result << %(</orderedlist>)
301
- result * LF
308
+ result.join LF
302
309
  end
303
310
 
304
311
  def open node
@@ -434,9 +441,9 @@ module Asciidoctor
434
441
  when :literal
435
442
  cell_content = %(<literallayout class="monospaced">#{cell.text}</literallayout>)
436
443
  when :header
437
- cell_content = (cell_content = cell.content).empty? ? '' : %(<simpara><emphasis role="strong">#{cell_content * '</emphasis></simpara><simpara><emphasis role="strong">'}</emphasis></simpara>)
444
+ cell_content = (cell_content = cell.content).empty? ? '' : %(<simpara><emphasis role="strong">#{cell_content.join '</emphasis></simpara><simpara><emphasis role="strong">'}</emphasis></simpara>)
438
445
  else
439
- cell_content = (cell_content = cell.content).empty? ? '' : %(<simpara>#{cell_content * '</simpara><simpara>'}</simpara>)
446
+ cell_content = (cell_content = cell.content).empty? ? '' : %(<simpara>#{cell_content.join '</simpara><simpara>'}</simpara>)
440
447
  end
441
448
  end
442
449
  entry_end = (node.document.attr? 'cellbgcolor') ? %(<?dbfo bgcolor="#{node.document.attr 'cellbgcolor'}"?></entry>) : '</entry>'
@@ -450,7 +457,7 @@ module Asciidoctor
450
457
  result << %(</#{tag_name}>)
451
458
 
452
459
  logger.warn 'tables must have at least one body row' unless has_body
453
- result * LF
460
+ result.join LF
454
461
  end
455
462
 
456
463
  alias toc skip
@@ -486,7 +493,7 @@ module Asciidoctor
486
493
  result << '</itemizedlist>'
487
494
  end
488
495
 
489
- result * LF
496
+ result.join LF
490
497
  end
491
498
 
492
499
  def verse node
@@ -568,7 +575,7 @@ module Asciidoctor
568
575
  result << %(<indexterm>
569
576
  <primary>#{terms[-1]}</primary>
570
577
  </indexterm>)
571
- result * LF
578
+ result.join LF
572
579
  end
573
580
  end
574
581
 
@@ -576,7 +583,7 @@ module Asciidoctor
576
583
  if (keys = node.attr 'keys').size == 1
577
584
  %(<keycap>#{keys[0]}</keycap>)
578
585
  else
579
- %(<keycombo><keycap>#{keys * '</keycap><keycap>'}</keycap></keycombo>)
586
+ %(<keycombo><keycap>#{keys.join '</keycap><keycap>'}</keycap></keycombo>)
580
587
  end
581
588
  end
582
589
 
@@ -589,7 +596,7 @@ module Asciidoctor
589
596
  %(<guimenu>#{menu}</guimenu>)
590
597
  end
591
598
  else
592
- %(<menuchoice><guimenu>#{menu}</guimenu> <guisubmenu>#{submenus * '</guisubmenu> <guisubmenu>'}</guisubmenu> <guimenuitem>#{node.attr 'menuitem'}</guimenuitem></menuchoice>)
599
+ %(<menuchoice><guimenu>#{menu}</guimenu> <guisubmenu>#{submenus.join '</guisubmenu> <guisubmenu>'}</guisubmenu> <guimenuitem>#{node.attr 'menuitem'}</guimenuitem></menuchoice>)
593
600
  end
594
601
  end
595
602
 
@@ -649,23 +656,17 @@ module Asciidoctor
649
656
  nil
650
657
  end
651
658
 
652
- def author_tag doc, index = nil
653
- firstname_key = index ? %(firstname_#{index}) : 'firstname'
654
- middlename_key = index ? %(middlename_#{index}) : 'middlename'
655
- lastname_key = index ? %(lastname_#{index}) : 'lastname'
656
- email_key = index ? %(email_#{index}) : 'email'
657
-
659
+ def author_tag author
658
660
  result = []
659
661
  result << '<author>'
660
662
  result << '<personname>'
661
- result << %(<firstname>#{doc.attr firstname_key}</firstname>) if doc.attr? firstname_key
662
- result << %(<othername>#{doc.attr middlename_key}</othername>) if doc.attr? middlename_key
663
- result << %(<surname>#{doc.attr lastname_key}</surname>) if doc.attr? lastname_key
663
+ result << %(<firstname>#{author.firstname}</firstname>) if author.firstname
664
+ result << %(<othername>#{author.middlename}</othername>) if author.middlename
665
+ result << %(<surname>#{author.lastname}</surname>) if author.lastname
664
666
  result << '</personname>'
665
- result << %(<email>#{doc.attr email_key}</email>) if doc.attr? email_key
667
+ result << %(<email>#{author.email}</email>) if author.email
666
668
  result << '</author>'
667
-
668
- result * LF
669
+ result.join LF
669
670
  end
670
671
 
671
672
  def document_info_tag doc, info_tag_prefix, use_info_tag_prefix = false
@@ -684,16 +685,14 @@ module Asciidoctor
684
685
  result << '</copyright>'
685
686
  end
686
687
  if doc.has_header?
687
- if doc.attr? 'author'
688
- if (authorcount = (doc.attr 'authorcount').to_i) < 2
689
- result << (author_tag doc)
690
- result << %(<authorinitials>#{doc.attr 'authorinitials'}</authorinitials>) if doc.attr? 'authorinitials'
691
- else
688
+ unless (authors = doc.authors).empty?
689
+ if authors.size > 1
692
690
  result << '<authorgroup>'
693
- authorcount.times do |index|
694
- result << (author_tag doc, index + 1)
695
- end
691
+ authors.each {|author| result << (author_tag author) }
696
692
  result << '</authorgroup>'
693
+ else
694
+ result << author_tag(author = authors[0])
695
+ result << %(<authorinitials>#{author.initials}</authorinitials>) if author.initials
697
696
  end
698
697
  end
699
698
  if (doc.attr? 'revdate') && ((doc.attr? 'revnumber') || (doc.attr? 'revremark'))
@@ -736,7 +735,7 @@ module Asciidoctor
736
735
  result << '</refnamediv>'
737
736
  end
738
737
 
739
- result * LF
738
+ result.join LF
740
739
  end
741
740
 
742
741
  def document_ns_attributes doc
@@ -810,7 +809,7 @@ module Asciidoctor
810
809
  end
811
810
  result << yield
812
811
  result << end_tag
813
- result * LF
812
+ result.join LF
814
813
  end
815
814
  end
816
815
  end
@@ -23,7 +23,7 @@ module Asciidoctor
23
23
  # DocBook 5} and {DocBook45Converter DocBook 4.5}, as well as any custom
24
24
  # converters that have been discovered or explicitly registered.
25
25
  #
26
- # If the {https://rubygems.org/gems/thread_safe thread_safe} gem is
26
+ # If the {https://rubygems.org/gems/concurrent-ruby concurrent-ruby} gem is
27
27
  # installed, access to the default factory is guaranteed to be thread safe.
28
28
  # Otherwise, a warning is issued to the user.
29
29
  class Factory
@@ -32,8 +32,8 @@ module Asciidoctor
32
32
 
33
33
  # Public: Retrieves a singleton instance of {Factory Converter::Factory}.
34
34
  #
35
- # If the thread_safe gem is installed, the registry of converters is
36
- # initialized as a ThreadSafe::Cache. Otherwise, a warning is issued and
35
+ # If the concurrent-ruby gem is installed, the registry of converters is
36
+ # initialized as a Concurrent::Hash. Otherwise, a warning is issued and
37
37
  # the registry of converters is initialized using a normal Hash.
38
38
  #
39
39
  # initialize_singleton - A Boolean to indicate whether the singleton should
@@ -44,14 +44,16 @@ module Asciidoctor
44
44
  # Returns the default [Factory] singleton instance
45
45
  def default initialize_singleton = true
46
46
  return @__default__ || new unless initialize_singleton
47
- # FIXME this assignment is not thread_safe, may need to use a ::Threadsafe helper here
47
+ # FIXME this assignment itself may not be thread safe; may need to use a helper here
48
48
  @__default__ ||= begin
49
- # NOTE .to_s hides require from Opal
50
- require 'thread_safe'.to_s unless defined? ::ThreadSafe
51
- new ::ThreadSafe::Cache.new
49
+ unless defined? ::Concurrent::Hash
50
+ # NOTE dynamic require is ignored by Opal
51
+ require ::RUBY_MIN_VERSION_1_9 ? 'concurrent/hash' : 'asciidoctor/core_ext/1.8.7/concurrent/hash'
52
+ end
53
+ new ::Concurrent::Hash.new
52
54
  rescue ::LoadError
53
55
  include Logging unless include? Logging
54
- logger.warn 'gem \'thread_safe\' is not installed. This gem is recommended when registering custom converters.'
56
+ logger.warn 'gem \'concurrent-ruby\' is not installed. This gem is recommended when registering custom converters.'
55
57
  new
56
58
  end
57
59
  end
@@ -56,7 +56,7 @@ module Asciidoctor
56
56
  if (icon_href = node.attr 'favicon').empty?
57
57
  icon_href, icon_type = 'favicon.ico', 'image/x-icon'
58
58
  else
59
- icon_type = (icon_ext = ::File.extname icon_href) == '.ico' ? 'image/x-icon' : %(image/#{icon_ext[1..-1]})
59
+ icon_type = (icon_ext = ::File.extname icon_href) == '.ico' ? 'image/x-icon' : %(image/#{icon_ext.slice 1, icon_ext.length})
60
60
  end
61
61
  result << %(<link rel="icon" type="#{icon_type}" href="#{icon_href}"#{slash}>)
62
62
  end
@@ -122,9 +122,9 @@ module Asciidoctor
122
122
  classes = [node.doctype]
123
123
  end
124
124
  classes << (node.attr 'docrole') if node.attr? 'docrole'
125
- body_attrs << %(class="#{classes * ' '}")
125
+ body_attrs << %(class="#{classes.join ' '}")
126
126
  body_attrs << %(style="max-width: #{node.attr 'max-width'};") if node.attr? 'max-width'
127
- result << %(<body #{body_attrs * ' '}>)
127
+ result << %(<body #{body_attrs.join ' '}>)
128
128
 
129
129
  unless node.noheader
130
130
  result << '<div id="header">'
@@ -141,19 +141,11 @@ module Asciidoctor
141
141
  if node.has_header?
142
142
  result << %(<h1>#{node.header.title}</h1>) unless node.notitle
143
143
  details = []
144
- if node.attr? 'author'
145
- details << %(<span id="author" class="author">#{node.attr 'author'}</span>#{br})
146
- if node.attr? 'email'
147
- details << %(<span id="email" class="email">#{node.sub_macros(node.attr 'email')}</span>#{br})
148
- end
149
- if (authorcount = (node.attr 'authorcount').to_i) > 1
150
- (2..authorcount).each do |idx|
151
- details << %(<span id="author#{idx}" class="author">#{node.attr "author_#{idx}"}</span>#{br})
152
- if node.attr? %(email_#{idx})
153
- details << %(<span id="email#{idx}" class="email">#{node.sub_macros(node.attr "email_#{idx}")}</span>#{br})
154
- end
155
- end
156
- end
144
+ idx = 1
145
+ node.authors.each do |author|
146
+ details << %(<span id="author#{idx > 1 ? idx : ''}" class="author">#{author.name}</span>#{br})
147
+ details << %(<span id="email#{idx > 1 ? idx : ''}" class="email">#{node.sub_macros author.email}</span>#{br}) if author.email
148
+ idx += 1
157
149
  end
158
150
  if node.attr? 'revnumber'
159
151
  details << %(<span id="revnumber">#{((node.attr 'version-label') || '').downcase} #{node.attr 'revnumber'}#{(node.attr? 'revdate') ? ',' : ''}</span>)
@@ -213,7 +205,7 @@ module Asciidoctor
213
205
  # See http://www.html5rocks.com/en/tutorials/speed/script-loading/
214
206
  case highlighter
215
207
  when 'highlightjs', 'highlight.js'
216
- highlightjs_path = node.attr 'highlightjsdir', %(#{cdn_base}/highlight.js/9.12.0)
208
+ highlightjs_path = node.attr 'highlightjsdir', %(#{cdn_base}/highlight.js/9.13.1)
217
209
  result << %(<link rel="stylesheet" href="#{highlightjs_path}/styles/#{node.attr 'highlightjs-theme', 'github'}.min.css"#{slash}>)
218
210
  result << %(<script src="#{highlightjs_path}/highlight.min.js"></script>
219
211
  <script>hljs.initHighlighting()</script>)
@@ -249,7 +241,7 @@ MathJax.Hub.Config({
249
241
 
250
242
  result << '</body>'
251
243
  result << '</html>'
252
- result * LF
244
+ result.join LF
253
245
  end
254
246
 
255
247
  def embedded node
@@ -288,13 +280,13 @@ MathJax.Hub.Config({
288
280
  result << '</div>'
289
281
  end
290
282
 
291
- result * LF
283
+ result.join LF
292
284
  end
293
285
 
294
286
  def outline node, opts = {}
295
287
  return unless node.sections?
296
- sectnumlevels = opts[:sectnumlevels] || (node.document.attr 'sectnumlevels', 3).to_i
297
- toclevels = opts[:toclevels] || (node.document.attr 'toclevels', 2).to_i
288
+ sectnumlevels = opts[:sectnumlevels] || (node.document.attributes['sectnumlevels'] || 3).to_i
289
+ toclevels = opts[:toclevels] || (node.document.attributes['toclevels'] || 2).to_i
298
290
  sections = node.sections
299
291
  # FIXME top level is incorrect if a multipart book starts with a special section defined at level 0
300
292
  result = [%(<ul class="sectlevel#{sections[0].level}">)]
@@ -303,12 +295,22 @@ MathJax.Hub.Config({
303
295
  if section.caption
304
296
  stitle = section.captioned_title
305
297
  elsif section.numbered && slevel <= sectnumlevels
306
- stitle = %(#{section.sectnum} #{section.title})
298
+ if slevel < 2 && node.document.doctype == 'book'
299
+ if section.sectname == 'chapter'
300
+ stitle = %(#{(signifier = node.document.attributes['chapter-signifier']) ? "#{signifier} " : ''}#{section.sectnum} #{section.title})
301
+ elsif section.sectname == 'part'
302
+ stitle = %(#{(signifier = node.document.attributes['part-signifier']) ? "#{signifier} " : ''}#{section.sectnum nil, ':'} #{section.title})
303
+ else
304
+ stitle = %(#{section.sectnum} #{section.title})
305
+ end
306
+ else
307
+ stitle = %(#{section.sectnum} #{section.title})
308
+ end
307
309
  else
308
310
  stitle = section.title
309
311
  end
310
312
  stitle = stitle.gsub DropAnchorRx, '' if stitle.include? '<a'
311
- if slevel < toclevels && (child_toc_level = outline section, :toclevels => toclevels, :secnumlevels => sectnumlevels)
313
+ if slevel < toclevels && (child_toc_level = outline section, :toclevels => toclevels, :sectnumlevels => sectnumlevels)
312
314
  result << %(<li><a href="##{section.id}">#{stitle}</a>)
313
315
  result << child_toc_level
314
316
  result << '</li>'
@@ -317,22 +319,35 @@ MathJax.Hub.Config({
317
319
  end
318
320
  end
319
321
  result << '</ul>'
320
- result * LF
322
+ result.join LF
321
323
  end
322
324
 
323
325
  def section node
324
- if (level = node.level) == 0
325
- sect0 = true
326
- title = node.numbered && level <= (node.document.attr 'sectnumlevels', 3).to_i ? %(#{node.sectnum} #{node.title}) : node.title
326
+ doc_attrs = node.document.attributes
327
+ level = node.level
328
+ if node.caption
329
+ title = node.captioned_title
330
+ elsif node.numbered && level <= (doc_attrs['sectnumlevels'] || 3).to_i
331
+ if level < 2 && node.document.doctype == 'book'
332
+ if node.sectname == 'chapter'
333
+ title = %(#{(signifier = doc_attrs['chapter-signifier']) ? "#{signifier} " : ''}#{node.sectnum} #{node.title})
334
+ elsif node.sectname == 'part'
335
+ title = %(#{(signifier = doc_attrs['part-signifier']) ? "#{signifier} " : ''}#{node.sectnum nil, ':'} #{node.title})
336
+ else
337
+ title = %(#{node.sectnum} #{node.title})
338
+ end
339
+ else
340
+ title = %(#{node.sectnum} #{node.title})
341
+ end
327
342
  else
328
- title = node.numbered && !node.caption && level <= (node.document.attr 'sectnumlevels', 3).to_i ? %(#{node.sectnum} #{node.title}) : node.captioned_title
343
+ title = node.title
329
344
  end
330
345
  if node.id
331
346
  id_attr = %( id="#{id = node.id}")
332
- if (doc_attrs = node.document.attributes).key? 'sectlinks'
347
+ if doc_attrs['sectlinks']
333
348
  title = %(<a class="link" href="##{id}">#{title}</a>)
334
349
  end
335
- if doc_attrs.key? 'sectanchors'
350
+ if doc_attrs['sectanchors']
336
351
  # QUESTION should we add a font-based icon in anchor if icons=font?
337
352
  if doc_attrs['sectanchors'] == 'after'
338
353
  title = %(#{title}<a class="anchor" href="##{id}"></a>)
@@ -343,8 +358,7 @@ MathJax.Hub.Config({
343
358
  else
344
359
  id_attr = ''
345
360
  end
346
-
347
- if sect0
361
+ if level == 0
348
362
  %(<h1#{id_attr} class="sect0#{(role = node.role) ? " #{role}" : ''}">#{title}</h1>
349
363
  #{node.content})
350
364
  else
@@ -388,7 +402,7 @@ MathJax.Hub.Config({
388
402
  xml = @xml_mode
389
403
  id_attribute = node.id ? %( id="#{node.id}") : ''
390
404
  classes = ['audioblock', node.role].compact
391
- class_attribute = %( class="#{classes * ' '}")
405
+ class_attribute = %( class="#{classes.join ' '}")
392
406
  title_element = node.title? ? %(<div class="title">#{node.title}</div>\n) : ''
393
407
  start_t = node.attr 'start', nil, false
394
408
  end_t = node.attr 'end', nil, false
@@ -406,7 +420,7 @@ Your browser does not support the audio tag.
406
420
  result = []
407
421
  id_attribute = node.id ? %( id="#{node.id}") : ''
408
422
  classes = ['colist', node.style, node.role].compact
409
- class_attribute = %( class="#{classes * ' '}")
423
+ class_attribute = %( class="#{classes.join ' '}")
410
424
 
411
425
  result << %(<div#{id_attribute}#{class_attribute}>)
412
426
  result << %(<div class="title">#{node.title}</div>) if node.title?
@@ -438,7 +452,7 @@ Your browser does not support the audio tag.
438
452
  end
439
453
 
440
454
  result << '</div>'
441
- result * LF
455
+ result.join LF
442
456
  end
443
457
 
444
458
  def dlist node
@@ -454,7 +468,7 @@ Your browser does not support the audio tag.
454
468
  ['dlist', node.style, node.role]
455
469
  end.compact
456
470
 
457
- class_attribute = %( class="#{classes * ' '}")
471
+ class_attribute = %( class="#{classes.join ' '}")
458
472
 
459
473
  result << %(<div#{id_attribute}#{class_attribute}>)
460
474
  result << %(<div class="title">#{node.title}</div>) if node.title?
@@ -521,7 +535,7 @@ Your browser does not support the audio tag.
521
535
  end
522
536
 
523
537
  result << '</div>'
524
- result * LF
538
+ result.join LF
525
539
  end
526
540
 
527
541
  def example node
@@ -539,7 +553,7 @@ Your browser does not support the audio tag.
539
553
  tag_name = %(h#{node.level + 1})
540
554
  id_attribute = node.id ? %( id="#{node.id}") : ''
541
555
  classes = [node.style, node.role].compact
542
- %(<#{tag_name}#{id_attribute} class="#{classes * ' '}">#{node.title}</#{tag_name}>)
556
+ %(<#{tag_name}#{id_attribute} class="#{classes.join ' '}">#{node.title}</#{tag_name}>)
543
557
  end
544
558
 
545
559
  def image node
@@ -560,14 +574,13 @@ Your browser does not support the audio tag.
560
574
  img = %(<a class="image" href="#{node.attr 'link'}"#{(append_link_constraint_attrs node).join}>#{img}</a>)
561
575
  end
562
576
  id_attr = node.id ? %( id="#{node.id}") : ''
563
- classes = ['imageblock', node.role].compact
564
- class_attr = %( class="#{classes * ' '}")
565
- styles = []
566
- styles << %(text-align: #{node.attr 'align'}) if node.attr? 'align'
567
- styles << %(float: #{node.attr 'float'}) if node.attr? 'float'
568
- style_attr = styles.empty? ? '' : %( style="#{styles * ';'}")
577
+ classes = ['imageblock']
578
+ classes << (node.attr 'float') if node.attr? 'float'
579
+ classes << %(text-#{node.attr 'align'}) if node.attr? 'align'
580
+ classes << node.role if node.role
581
+ class_attr = %( class="#{classes.join ' '}")
569
582
  title_el = node.title? ? %(\n<div class="title">#{node.captioned_title}</div>) : ''
570
- %(<div#{id_attr}#{class_attr}#{style_attr}>
583
+ %(<div#{id_attr}#{class_attr}>
571
584
  <div class="content">
572
585
  #{img}
573
586
  </div>#{title_el}
@@ -658,7 +671,7 @@ Your browser does not support the audio tag.
658
671
  result = []
659
672
  id_attribute = node.id ? %( id="#{node.id}") : ''
660
673
  classes = ['olist', node.style, node.role].compact
661
- class_attribute = %( class="#{classes * ' '}")
674
+ class_attribute = %( class="#{classes.join ' '}")
662
675
 
663
676
  result << %(<div#{id_attribute}#{class_attribute}>)
664
677
  result << %(<div class="title">#{node.title}</div>) if node.title?
@@ -677,7 +690,7 @@ Your browser does not support the audio tag.
677
690
 
678
691
  result << '</ol>'
679
692
  result << '</div>'
680
- result * LF
693
+ result.join LF
681
694
  end
682
695
 
683
696
  def open node
@@ -749,7 +762,7 @@ Your browser does not support the audio tag.
749
762
  def quote node
750
763
  id_attribute = node.id ? %( id="#{node.id}") : ''
751
764
  classes = ['quoteblock', node.role].compact
752
- class_attribute = %( class="#{classes * ' '}")
765
+ class_attribute = %( class="#{classes.join ' '}")
753
766
  title_element = node.title? ? %(\n<div class="title">#{node.title}</div>) : ''
754
767
  attribution = (node.attr? 'attribution') ? (node.attr 'attribution') : nil
755
768
  citetitle = (node.attr? 'citetitle') ? (node.attr 'citetitle') : nil
@@ -797,12 +810,12 @@ Your browser does not support the audio tag.
797
810
  else
798
811
  styles << %(width: #{tablewidth}%;)
799
812
  end
813
+ classes << (node.attr 'float') if node.attr? 'float'
800
814
  if (role = node.role)
801
815
  classes << role
802
816
  end
803
- class_attribute = %( class="#{classes * ' '}")
804
- styles << %(float: #{node.attr 'float'};) if node.attr? 'float'
805
- style_attribute = styles.empty? ? '' : %( style="#{styles * ' '}")
817
+ class_attribute = %( class="#{classes.join ' '}")
818
+ style_attribute = styles.empty? ? '' : %( style="#{styles.join ' '}")
806
819
 
807
820
  result << %(<table#{id_attribute}#{class_attribute}#{style_attribute}>)
808
821
  result << %(<caption class="title">#{node.captioned_title}</caption>) if node.title?
@@ -834,7 +847,7 @@ Your browser does not support the audio tag.
834
847
  when :literal
835
848
  cell_content = %(<div class="literal"><pre>#{cell.text}</pre></div>)
836
849
  else
837
- cell_content = (cell_content = cell.content).empty? ? '' : %(<p class="tableblock">#{cell_content * '</p>
850
+ cell_content = (cell_content = cell.content).empty? ? '' : %(<p class="tableblock">#{cell_content.join '</p>
838
851
  <p class="tableblock">'}</p>)
839
852
  end
840
853
  end
@@ -852,7 +865,7 @@ Your browser does not support the audio tag.
852
865
  end
853
866
  end
854
867
  result << '</table>'
855
- result * LF
868
+ result.join LF
856
869
  end
857
870
 
858
871
  def toc node
@@ -905,7 +918,7 @@ Your browser does not support the audio tag.
905
918
  else
906
919
  ul_class_attribute = node.style ? %( class="#{node.style}") : ''
907
920
  end
908
- result << %(<div#{id_attribute} class="#{div_classes * ' '}">)
921
+ result << %(<div#{id_attribute} class="#{div_classes.join ' '}">)
909
922
  result << %(<div class="title">#{node.title}</div>) if node.title?
910
923
  result << %(<ul#{ul_class_attribute}>)
911
924
 
@@ -922,13 +935,13 @@ Your browser does not support the audio tag.
922
935
 
923
936
  result << '</ul>'
924
937
  result << '</div>'
925
- result * LF
938
+ result.join LF
926
939
  end
927
940
 
928
941
  def verse node
929
942
  id_attribute = node.id ? %( id="#{node.id}") : ''
930
943
  classes = ['verseblock', node.role].compact
931
- class_attribute = %( class="#{classes * ' '}")
944
+ class_attribute = %( class="#{classes.join ' '}")
932
945
  title_element = node.title? ? %(\n<div class="title">#{node.title}</div>) : ''
933
946
  attribution = (node.attr? 'attribution') ? (node.attr 'attribution') : nil
934
947
  citetitle = (node.attr? 'citetitle') ? (node.attr 'citetitle') : nil
@@ -948,8 +961,11 @@ Your browser does not support the audio tag.
948
961
  def video node
949
962
  xml = @xml_mode
950
963
  id_attribute = node.id ? %( id="#{node.id}") : ''
951
- classes = ['videoblock', node.role].compact
952
- class_attribute = %( class="#{classes * ' '}")
964
+ classes = ['videoblock']
965
+ classes << (node.attr 'float') if node.attr? 'float'
966
+ classes << %(text-#{node.attr 'align'}) if node.attr? 'align'
967
+ classes << node.role if node.role
968
+ class_attribute = %( class="#{classes.join ' '}")
953
969
  title_element = node.title? ? %(\n<div class="title">#{node.title}</div>) : ''
954
970
  width_attribute = (node.attr? 'width') ? %( width="#{node.attr 'width'}") : ''
955
971
  height_attribute = (node.attr? 'height') ? %( height="#{node.attr 'height'}") : ''
@@ -1081,7 +1097,7 @@ Your browser does not support the video tag.
1081
1097
  src = node.icon_uri("callouts/#{node.text}")
1082
1098
  %(<img src="#{src}" alt="#{node.text}"#{@void_element_slash}>)
1083
1099
  else
1084
- %(<b class="conum">(#{node.text})</b>)
1100
+ %(#{node.attributes['guard']}<b class="conum">(#{node.text})</b>)
1085
1101
  end
1086
1102
  end
1087
1103
 
@@ -1125,9 +1141,18 @@ Your browser does not support the video tag.
1125
1141
  if node.attr? 'link', nil, false
1126
1142
  img = %(<a class="image" href="#{node.attr 'link'}"#{(append_link_constraint_attrs node).join}>#{img}</a>)
1127
1143
  end
1128
- class_attr_val = (role = node.role) ? %(#{type} #{role}) : type
1129
- style_attr = (node.attr? 'float') ? %( style="float: #{node.attr 'float'}") : ''
1130
- %(<span class="#{class_attr_val}"#{style_attr}>#{img}</span>)
1144
+ if (role = node.role)
1145
+ if node.attr? 'float'
1146
+ class_attr_val = %(#{type} #{node.attr 'float'} #{role})
1147
+ else
1148
+ class_attr_val = %(#{type} #{role})
1149
+ end
1150
+ elsif node.attr? 'float'
1151
+ class_attr_val = %(#{type} #{node.attr 'float'})
1152
+ else
1153
+ class_attr_val = type
1154
+ end
1155
+ %(<span class="#{class_attr_val}">#{img}</span>)
1131
1156
  end
1132
1157
 
1133
1158
  def inline_indexterm node
@@ -1138,7 +1163,7 @@ Your browser does not support the video tag.
1138
1163
  if (keys = node.attr 'keys').size == 1
1139
1164
  %(<kbd>#{keys[0]}</kbd>)
1140
1165
  else
1141
- %(<span class="keyseq"><kbd>#{keys * '</kbd>+<kbd>'}</kbd></span>)
1166
+ %(<span class="keyseq"><kbd>#{keys.join '</kbd>+<kbd>'}</kbd></span>)
1142
1167
  end
1143
1168
  end
1144
1169
 
@@ -1153,7 +1178,7 @@ Your browser does not support the video tag.
1153
1178
  %(<b class="menuref">#{menu}</b>)
1154
1179
  end
1155
1180
  else
1156
- %(<span class="menuseq"><b class="menu">#{menu}</b>#{caret}<b class="submenu">#{submenus * submenu_joiner}</b>#{caret}<b class="menuitem">#{node.attr 'menuitem'}</b></span>)
1181
+ %(<span class="menuseq"><b class="menu">#{menu}</b>#{caret}<b class="submenu">#{submenus.join submenu_joiner}</b>#{caret}<b class="menuitem">#{node.attr 'menuitem'}</b></span>)
1157
1182
  end
1158
1183
  end
1159
1184
 
@@ -1181,7 +1206,7 @@ Your browser does not support the video tag.
1181
1206
  end
1182
1207
 
1183
1208
  def generate_manname_section node
1184
- manname_title = (node.attr 'manname-title') || 'Name'
1209
+ manname_title = node.attr 'manname-title', 'Name'
1185
1210
  if (next_section = node.sections[0]) && (next_section_title = next_section.title) == next_section_title.upcase
1186
1211
  manname_title = manname_title.upcase
1187
1212
  end