asciidoctor 1.5.6.2 → 1.5.7

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of asciidoctor might be problematic. Click here for more details.

Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +330 -143
  3. data/README-fr.adoc +441 -0
  4. data/README-jp.adoc +418 -0
  5. data/README-zh_CN.adoc +430 -0
  6. data/README.adoc +454 -0
  7. data/Rakefile +57 -0
  8. data/asciidoctor.gemspec +7 -1
  9. data/data/locale/attributes-ar.adoc +22 -0
  10. data/data/locale/attributes-bg.adoc +22 -0
  11. data/data/locale/attributes-ca.adoc +22 -0
  12. data/data/locale/attributes-cs.adoc +22 -0
  13. data/data/locale/attributes-da.adoc +22 -0
  14. data/data/locale/attributes-de.adoc +22 -0
  15. data/data/locale/attributes-en.adoc +23 -0
  16. data/data/locale/attributes-es.adoc +22 -0
  17. data/data/locale/attributes-fa.adoc +22 -0
  18. data/data/locale/attributes-fi.adoc +22 -0
  19. data/data/locale/attributes-fr.adoc +22 -0
  20. data/data/locale/attributes-hu.adoc +22 -0
  21. data/data/locale/attributes-id.adoc +22 -0
  22. data/data/locale/attributes-it.adoc +22 -0
  23. data/data/locale/attributes-ja.adoc +22 -0
  24. data/data/locale/attributes-kr.adoc +22 -0
  25. data/data/locale/attributes-nb.adoc +22 -0
  26. data/data/locale/attributes-nl.adoc +22 -0
  27. data/data/locale/attributes-nn.adoc +22 -0
  28. data/data/locale/attributes-pl.adoc +22 -0
  29. data/data/locale/attributes-pt.adoc +22 -0
  30. data/data/locale/attributes-pt_BR.adoc +22 -0
  31. data/data/locale/attributes-ro.adoc +22 -0
  32. data/data/locale/attributes-ru.adoc +22 -0
  33. data/data/locale/attributes-sr.adoc +22 -0
  34. data/data/locale/attributes-sr_Latn.adoc +22 -0
  35. data/data/locale/attributes-tr.adoc +22 -0
  36. data/data/locale/attributes-uk.adoc +22 -0
  37. data/data/locale/attributes-zh_CN.adoc +22 -0
  38. data/data/locale/attributes-zh_TW.adoc +22 -0
  39. data/data/locale/attributes.adoc +8 -649
  40. data/data/stylesheets/asciidoctor-default.css +77 -72
  41. data/features/xref.feature +366 -7
  42. data/lib/asciidoctor.rb +107 -93
  43. data/lib/asciidoctor/abstract_block.rb +247 -239
  44. data/lib/asciidoctor/abstract_node.rb +56 -58
  45. data/lib/asciidoctor/block.rb +3 -3
  46. data/lib/asciidoctor/callouts.rb +1 -1
  47. data/lib/asciidoctor/cli/invoker.rb +36 -9
  48. data/lib/asciidoctor/cli/options.rb +63 -25
  49. data/lib/asciidoctor/converter.rb +23 -13
  50. data/lib/asciidoctor/converter/base.rb +4 -0
  51. data/lib/asciidoctor/converter/docbook45.rb +16 -9
  52. data/lib/asciidoctor/converter/docbook5.rb +115 -97
  53. data/lib/asciidoctor/converter/factory.rb +29 -31
  54. data/lib/asciidoctor/converter/html5.rb +229 -192
  55. data/lib/asciidoctor/converter/manpage.rb +72 -50
  56. data/lib/asciidoctor/converter/template.rb +12 -12
  57. data/lib/asciidoctor/core_ext.rb +5 -1
  58. data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +6 -0
  59. data/lib/asciidoctor/document.rb +168 -77
  60. data/lib/asciidoctor/extensions.rb +79 -47
  61. data/lib/asciidoctor/helpers.rb +33 -11
  62. data/lib/asciidoctor/inline.rb +3 -2
  63. data/lib/asciidoctor/list.rb +2 -1
  64. data/lib/asciidoctor/logging.rb +122 -0
  65. data/lib/asciidoctor/parser.rb +406 -382
  66. data/lib/asciidoctor/path_resolver.rb +169 -162
  67. data/lib/asciidoctor/reader.rb +166 -121
  68. data/lib/asciidoctor/section.rb +45 -28
  69. data/lib/asciidoctor/stylesheets.rb +13 -5
  70. data/lib/asciidoctor/substitutors.rb +328 -254
  71. data/lib/asciidoctor/table.rb +105 -48
  72. data/lib/asciidoctor/timings.rb +34 -6
  73. data/lib/asciidoctor/version.rb +1 -1
  74. data/man/asciidoctor.1 +41 -23
  75. data/man/asciidoctor.adoc +14 -8
  76. data/test/api_test.rb +1004 -0
  77. data/test/attributes_test.rb +241 -50
  78. data/test/blocks_test.rb +549 -124
  79. data/test/converter_test.rb +170 -78
  80. data/test/document_test.rb +208 -767
  81. data/test/extensions_test.rb +188 -53
  82. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +1 -1
  83. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +1 -1
  84. data/test/fixtures/file-with-missing-include.adoc +1 -0
  85. data/test/fixtures/include-file.jsx +8 -0
  86. data/test/fixtures/lists.adoc +96 -0
  87. data/test/fixtures/other-chapters.adoc +11 -0
  88. data/test/fixtures/outer-include.adoc +5 -0
  89. data/test/fixtures/sample.asciidoc +5 -1
  90. data/test/fixtures/subdir/index.adoc +3 -0
  91. data/test/fixtures/subdir/inner-include.adoc +3 -0
  92. data/test/fixtures/subdir/middle-include.adoc +5 -0
  93. data/test/fixtures/tagged-class-enclosed.rb +0 -1
  94. data/test/fixtures/unclosed-tag.adoc +3 -0
  95. data/test/fixtures/unexpected-end-tag.adoc +4 -0
  96. data/test/invoker_test.rb +101 -40
  97. data/test/links_test.rb +266 -72
  98. data/test/lists_test.rb +243 -45
  99. data/test/logger_test.rb +211 -0
  100. data/test/manpage_test.rb +124 -6
  101. data/test/options_test.rb +46 -1
  102. data/test/paragraphs_test.rb +23 -10
  103. data/test/parser_test.rb +30 -1
  104. data/test/paths_test.rb +115 -33
  105. data/test/preamble_test.rb +1 -1
  106. data/test/reader_test.rb +337 -81
  107. data/test/sections_test.rb +656 -72
  108. data/test/substitutions_test.rb +182 -57
  109. data/test/tables_test.rb +324 -57
  110. data/test/test_helper.rb +77 -32
  111. data/test/text_test.rb +7 -7
  112. metadata +67 -3
@@ -20,7 +20,7 @@ module Asciidoctor
20
20
  # super
21
21
  # outfilesuffix '.txt'
22
22
  # end
23
- # def convert node, transform = nil
23
+ # def convert node, transform = nil, opts = {}
24
24
  # case (transform ||= node.node_name)
25
25
  # when 'document'
26
26
  # node.content
@@ -86,44 +86,52 @@ module Asciidoctor
86
86
  syntax = 'html'
87
87
  end
88
88
  {
89
- 'basebackend' => base,
90
- 'outfilesuffix' => ext,
91
- 'filetype' => type,
92
- 'htmlsyntax' => syntax
89
+ :basebackend => base,
90
+ :outfilesuffix => ext,
91
+ :filetype => type,
92
+ :htmlsyntax => syntax
93
93
  }
94
94
  end
95
95
 
96
96
  def filetype value = nil
97
97
  if value
98
- backend_info['filetype'] = value
98
+ backend_info[:filetype] = value
99
99
  else
100
- backend_info['filetype']
100
+ backend_info[:filetype]
101
101
  end
102
102
  end
103
103
 
104
104
  def basebackend value = nil
105
105
  if value
106
- backend_info['basebackend'] = value
106
+ backend_info[:basebackend] = value
107
107
  else
108
- backend_info['basebackend']
108
+ backend_info[:basebackend]
109
109
  end
110
110
  end
111
111
 
112
112
  def outfilesuffix value = nil
113
113
  if value
114
- backend_info['outfilesuffix'] = value
114
+ backend_info[:outfilesuffix] = value
115
115
  else
116
- backend_info['outfilesuffix']
116
+ backend_info[:outfilesuffix]
117
117
  end
118
118
  end
119
119
 
120
120
  def htmlsyntax value = nil
121
121
  if value
122
- backend_info['htmlsyntax'] = value
122
+ backend_info[:htmlsyntax] = value
123
123
  else
124
- backend_info['htmlsyntax']
124
+ backend_info[:htmlsyntax]
125
125
  end
126
126
  end
127
+
128
+ def supports_templates
129
+ backend_info[:supports_templates] = true
130
+ end
131
+
132
+ def supports_templates?
133
+ backend_info[:supports_templates]
134
+ end
127
135
  end
128
136
 
129
137
  class << self
@@ -183,6 +191,8 @@ module Asciidoctor
183
191
  raise ::NotImplementedError
184
192
  end
185
193
 
194
+ alias handles? respond_to?
195
+
186
196
  # Alias for backward compatibility.
187
197
  alias convert_with_options convert
188
198
  end
@@ -9,11 +9,15 @@ module Asciidoctor
9
9
  # Concrete subclasses must implement the {#convert} method and, optionally,
10
10
  # the {#convert_with_options} method.
11
11
  class Converter::Base
12
+ include Logging
12
13
  include Converter
13
14
  end
14
15
 
15
16
  # An abstract base class for built-in {Converter} classes.
17
+ # Does not inherit from Converter.
16
18
  class Converter::BuiltIn
19
+ include Logging
20
+
17
21
  def initialize backend, opts = {}
18
22
  end
19
23
 
@@ -18,8 +18,8 @@ module Asciidoctor
18
18
 
19
19
  def olist node
20
20
  result = []
21
- num_attribute = node.style ? %( numeration="#{node.style}") : nil
22
- start_attribute = (node.attr? 'start') ? %( override="#{node.attr 'start'}") : nil
21
+ num_attribute = node.style ? %( numeration="#{node.style}") : ''
22
+ start_attribute = (node.attr? 'start') ? %( override="#{node.attr 'start'}") : ''
23
23
  result << %(<orderedlist#{common_attributes node.id, node.role, node.reftext}#{num_attribute}>)
24
24
  result << %(<title>#{node.title}</title>) if node.title?
25
25
  node.items.each_with_index do |item, idx|
@@ -52,11 +52,18 @@ module Asciidoctor
52
52
  end
53
53
  end
54
54
 
55
- def author_element doc, index = nil
56
- firstname_key = index ? %(firstname_#{index}) : 'firstname'
57
- middlename_key = index ? %(middlename_#{index}) : 'middlename'
58
- lastname_key = index ? %(lastname_#{index}) : 'lastname'
59
- email_key = index ? %(email_#{index}) : 'email'
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
60
67
 
61
68
  result = []
62
69
  result << '<author>'
@@ -80,7 +87,7 @@ module Asciidoctor
80
87
  %(<!DOCTYPE #{root_tag_name} PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">)
81
88
  end
82
89
 
83
- def document_info_element doc, info_tag_prefix
90
+ def document_info_tag doc, info_tag_prefix
84
91
  super doc, info_tag_prefix, true
85
92
  end
86
93
 
@@ -92,7 +99,7 @@ module Asciidoctor
92
99
  if (ns = doc.attr 'xmlns')
93
100
  ns.empty? ? ' xmlns="http://docbook.org/ns/docbook"' : %( xmlns="#{ns}")
94
101
  else
95
- nil
102
+ ''
96
103
  end
97
104
  end
98
105
  end
@@ -4,6 +4,7 @@ module Asciidoctor
4
4
  # similar to the docbook45 backend from AsciiDoc Python, but migrated to the
5
5
  # DocBook 5 specification.
6
6
  class Converter::DocBook5Converter < Converter::BuiltIn
7
+ CopyrightRx = /^(.+?)(?: ((?:\d{4}\-)?\d{4}))?$/
7
8
  ImageMacroRx = /^image::?(.+?)\[(.*?)\]$/
8
9
 
9
10
  def document node
@@ -29,9 +30,9 @@ module Asciidoctor
29
30
  result << '<?asciidoc-numbered?>'
30
31
  end
31
32
  end
32
- lang_attribute = (node.attr? 'nolang') ? nil : %( #{lang_attribute_name}="#{node.attr 'lang', 'en'}")
33
+ lang_attribute = (node.attr? 'nolang') ? '' : %( #{lang_attribute_name}="#{node.attr 'lang', 'en'}")
33
34
  result << %(<#{root_tag_name}#{document_ns_attributes node}#{lang_attribute}>)
34
- result << (document_info_element node, root_tag_name) unless node.noheader
35
+ result << (document_info_tag node, root_tag_name) unless node.noheader
35
36
  result << node.content if node.blocks?
36
37
  unless (footer_docinfo = node.docinfo :footer).empty?
37
38
  result << footer_docinfo
@@ -51,9 +52,9 @@ module Asciidoctor
51
52
  else
52
53
  tag_name = node.sectname
53
54
  end
55
+ title_el = node.special && (node.option? 'untitled') ? '' : %(<title>#{node.title}</title>\n)
54
56
  %(<#{tag_name}#{common_attributes node.id, node.role, node.reftext}>
55
- <title>#{node.title}</title>
56
- #{node.content}
57
+ #{title_el}#{node.content}
57
58
  </#{tag_name}>)
58
59
  end
59
60
 
@@ -116,7 +117,7 @@ module Asciidoctor
116
117
  end
117
118
  result << %(</entry>
118
119
  <entry>)
119
- unless dd.nil?
120
+ if dd
120
121
  result << %(<simpara>#{dd.text}</simpara>) if dd.text?
121
122
  result << dd.content if dd.blocks?
122
123
  end
@@ -148,7 +149,7 @@ module Asciidoctor
148
149
 
149
150
  result << %(</#{label_tag}>) if label_tag
150
151
  result << %(<#{item_tag}>)
151
- unless dd.nil?
152
+ if dd
152
153
  result << %(<simpara>#{dd.text}</simpara>) if dd.text?
153
154
  result << dd.content if dd.blocks?
154
155
  end
@@ -184,19 +185,19 @@ module Asciidoctor
184
185
  # See http://tdg.docbook.org/tdg/4.5/imagedata-x.html#d0e79635
185
186
  if node.attr? 'scaledwidth'
186
187
  width_attribute = %( width="#{node.attr 'scaledwidth'}")
187
- depth_attribute = nil
188
- scale_attribute = nil
188
+ depth_attribute = ''
189
+ scale_attribute = ''
189
190
  elsif node.attr? 'scale'
190
191
  # QUESTION should we set the viewport using width and depth? (the scaled image would be contained within this box)
191
- #width_attribute = (node.attr? 'width') ? %( width="#{node.attr 'width'}") : nil
192
- #depth_attribute = (node.attr? 'height') ? %( depth="#{node.attr 'height'}") : nil
192
+ #width_attribute = (node.attr? 'width') ? %( width="#{node.attr 'width'}") : ''
193
+ #depth_attribute = (node.attr? 'height') ? %( depth="#{node.attr 'height'}") : ''
193
194
  scale_attribute = %( scale="#{node.attr 'scale'}")
194
195
  else
195
- width_attribute = (node.attr? 'width') ? %( contentwidth="#{node.attr 'width'}") : nil
196
- depth_attribute = (node.attr? 'height') ? %( contentdepth="#{node.attr 'height'}") : nil
197
- scale_attribute = nil
196
+ width_attribute = (node.attr? 'width') ? %( contentwidth="#{node.attr 'width'}") : ''
197
+ depth_attribute = (node.attr? 'height') ? %( contentdepth="#{node.attr 'height'}") : ''
198
+ scale_attribute = ''
198
199
  end
199
- align_attribute = (node.attr? 'align') ? %( align="#{node.attr 'align'}") : nil
200
+ align_attribute = (node.attr? 'align') ? %( align="#{node.attr 'align'}") : ''
200
201
 
201
202
  mediaobject = %(<mediaobject>
202
203
  <imageobject>
@@ -222,9 +223,9 @@ module Asciidoctor
222
223
  listing_attributes = (common_attributes node.id, node.role, node.reftext)
223
224
  if node.style == 'source' && (node.attr? 'language')
224
225
  numbering = (node.attr? 'linenums', nil, false) ? 'numbered' : 'unnumbered'
225
- listing_content = %(<programlisting#{informal ? listing_attributes : nil} language="#{node.attr 'language', nil, false}" linenumbering="#{numbering}">#{node.content}</programlisting>)
226
+ listing_content = %(<programlisting#{informal ? listing_attributes : ''} language="#{node.attr 'language', '', false}" linenumbering="#{numbering}">#{node.content}</programlisting>)
226
227
  else
227
- listing_content = %(<screen#{informal ? listing_attributes : nil}>#{node.content}</screen>)
228
+ listing_content = %(<screen#{informal ? listing_attributes : ''}>#{node.content}</screen>)
228
229
  end
229
230
  if informal
230
231
  listing_content
@@ -260,8 +261,7 @@ module Asciidoctor
260
261
  equation = node.content
261
262
  end
262
263
  if node.style == 'asciimath'
263
- if ((defined? ::AsciiMath) || ((defined? @asciimath_available) ? @asciimath_available :
264
- (@asciimath_available = Helpers.require_library 'asciimath', true, :warn)))
264
+ if (@asciimath ||= ((defined? ::AsciiMath) || (Helpers.require_library 'asciimath', true, :warn)).nil? ? :unavailable : :loaded) == :loaded
265
265
  # NOTE fop requires jeuclid to process raw mathml
266
266
  equation_data = (::AsciiMath.parse equation).to_mathml 'mml:', 'xmlns:mml' => 'http://www.w3.org/1998/Math/MathML'
267
267
  else
@@ -287,8 +287,8 @@ module Asciidoctor
287
287
 
288
288
  def olist node
289
289
  result = []
290
- num_attribute = node.style ? %( numeration="#{node.style}") : nil
291
- start_attribute = (node.attr? 'start') ? %( startingnumber="#{node.attr 'start'}") : nil
290
+ num_attribute = node.style ? %( numeration="#{node.style}") : ''
291
+ start_attribute = (node.attr? 'start') ? %( startingnumber="#{node.attr 'start'}") : ''
292
292
  result << %(<orderedlist#{common_attributes node.id, node.role, node.reftext}#{num_attribute}#{start_attribute}>)
293
293
  result << %(<title>#{node.title}</title>) if node.title?
294
294
  node.items.each do |item|
@@ -305,7 +305,7 @@ module Asciidoctor
305
305
  case node.style
306
306
  when 'abstract'
307
307
  if node.parent == node.document && node.document.doctype == 'book'
308
- warn 'asciidoctor: WARNING: abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
308
+ logger.warn 'abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
309
309
  ''
310
310
  else
311
311
  %(<abstract>
@@ -314,7 +314,7 @@ module Asciidoctor
314
314
  end
315
315
  when 'partintro'
316
316
  unless node.level == 0 && node.parent.context == :section && node.document.doctype == 'book'
317
- warn 'asciidoctor: ERROR: partintro block can only be used when doctype is book and it\'s a child of a part section. Excluding block content.'
317
+ logger.error 'partintro block can only be used when doctype is book and must be a child of a book part. Excluding block content.'
318
318
  ''
319
319
  else
320
320
  %(<partintro#{common_attributes node.id, node.role, node.reftext}>
@@ -322,7 +322,24 @@ module Asciidoctor
322
322
  </partintro>)
323
323
  end
324
324
  else
325
- node.content
325
+ reftext = node.reftext if (id = node.id)
326
+ role = node.role
327
+ if node.title?
328
+ %(<formalpara#{common_attributes id, role, reftext}>
329
+ <title>#{node.title}</title>
330
+ <para>#{content_spacer = node.content_model == :compound ? LF : ''}#{node.content}#{content_spacer}</para>
331
+ </formalpara>)
332
+ elsif id || role
333
+ if node.content_model == :compound
334
+ %(<para#{common_attributes id, role, reftext}>
335
+ #{node.content}
336
+ </para>)
337
+ else
338
+ %(<simpara#{common_attributes id, role, reftext}>#{node.content}</simpara>)
339
+ end
340
+ else
341
+ resolve_content node
342
+ end
326
343
  end
327
344
  end
328
345
 
@@ -352,22 +369,7 @@ module Asciidoctor
352
369
  end
353
370
 
354
371
  def quote node
355
- result = []
356
- result << %(<blockquote#{common_attributes node.id, node.role, node.reftext}>)
357
- result << %(<title>#{node.title}</title>) if node.title?
358
- if (node.attr? 'attribution') || (node.attr? 'citetitle')
359
- result << '<attribution>'
360
- if node.attr? 'attribution'
361
- result << (node.attr 'attribution')
362
- end
363
- if node.attr? 'citetitle'
364
- result << %(<citetitle>#{node.attr 'citetitle'}</citetitle>)
365
- end
366
- result << '</attribution>'
367
- end
368
- result << (resolve_content node)
369
- result << '</blockquote>'
370
- result * LF
372
+ blockquote_tag(node, (node.has_role? 'epigraph') && 'epigraph') { resolve_content node }
371
373
  end
372
374
 
373
375
  def thematic_break node
@@ -385,8 +387,11 @@ module Asciidoctor
385
387
  def table node
386
388
  has_body = false
387
389
  result = []
388
- pgwide_attribute = (node.option? 'pgwide') ? ' pgwide="1"' : nil
389
- result << %(<#{tag_name = node.title? ? 'table' : 'informaltable'}#{common_attributes node.id, node.role, node.reftext}#{pgwide_attribute} frame="#{node.attr 'frame', 'all'}" rowsep="#{['none', 'cols'].include?(node.attr 'grid') ? 0 : 1}" colsep="#{['none', 'rows'].include?(node.attr 'grid') ? 0 : 1}"#{(node.attr? 'orientation', 'landscape', nil) ? ' orient="land"' : nil}>)
390
+ pgwide_attribute = (node.option? 'pgwide') ? ' pgwide="1"' : ''
391
+ if (frame = node.attr 'frame', 'all') == 'ends'
392
+ frame = 'topbot'
393
+ end
394
+ result << %(<#{tag_name = node.title? ? 'table' : 'informaltable'}#{common_attributes node.id, node.role, node.reftext}#{pgwide_attribute} frame="#{frame}" rowsep="#{['none', 'cols'].include?(node.attr 'grid') ? 0 : 1}" colsep="#{['none', 'rows'].include?(node.attr 'grid') ? 0 : 1}"#{(node.attr? 'orientation', 'landscape', false) ? ' orient="land"' : ''}>)
390
395
  if (node.option? 'unbreakable')
391
396
  result << '<?dbfo keep-together="always"?>'
392
397
  elsif (node.option? 'breakable')
@@ -412,10 +417,10 @@ module Asciidoctor
412
417
  rows.each do |row|
413
418
  result << '<row>'
414
419
  row.each do |cell|
415
- halign_attribute = (cell.attr? 'halign') ? %( align="#{cell.attr 'halign'}") : nil
416
- valign_attribute = (cell.attr? 'valign') ? %( valign="#{cell.attr 'valign'}") : nil
417
- colspan_attribute = cell.colspan ? %( namest="col_#{colnum = cell.column.attr 'colnumber'}" nameend="col_#{colnum + cell.colspan - 1}") : nil
418
- rowspan_attribute = cell.rowspan ? %( morerows="#{cell.rowspan - 1}") : nil
420
+ halign_attribute = (cell.attr? 'halign') ? %( align="#{cell.attr 'halign'}") : ''
421
+ valign_attribute = (cell.attr? 'valign') ? %( valign="#{cell.attr 'valign'}") : ''
422
+ colspan_attribute = cell.colspan ? %( namest="col_#{colnum = cell.column.attr 'colnumber'}" nameend="col_#{colnum + cell.colspan - 1}") : ''
423
+ rowspan_attribute = cell.rowspan ? %( morerows="#{cell.rowspan - 1}") : ''
419
424
  # NOTE <entry> may not have whitespace (e.g., line breaks) as a direct descendant according to DocBook rules
420
425
  entry_start = %(<entry#{halign_attribute}#{valign_attribute}#{colspan_attribute}#{rowspan_attribute}>)
421
426
  if tsec == :head
@@ -444,7 +449,7 @@ module Asciidoctor
444
449
  result << '</tgroup>'
445
450
  result << %(</#{tag_name}>)
446
451
 
447
- warn 'asciidoctor: WARNING: tables must have at least one body row' unless has_body
452
+ logger.warn 'tables must have at least one body row' unless has_body
448
453
  result * LF
449
454
  end
450
455
 
@@ -464,14 +469,14 @@ module Asciidoctor
464
469
  result << '</bibliodiv>'
465
470
  else
466
471
  mark_type = (checklist = node.option? 'checklist') ? 'none' : node.style
467
- mark_attribute = mark_type ? %( mark="#{mark_type}") : nil
472
+ mark_attribute = mark_type ? %( mark="#{mark_type}") : ''
468
473
  result << %(<itemizedlist#{common_attributes node.id, node.role, node.reftext}#{mark_attribute}>)
469
474
  result << %(<title>#{node.title}</title>) if node.title?
470
475
  node.items.each do |item|
471
476
  text_marker = if checklist && (item.attr? 'checkbox')
472
477
  (item.attr? 'checked') ? '&#10003; ' : '&#10063; '
473
478
  else
474
- nil
479
+ ''
475
480
  end
476
481
  result << '<listitem>'
477
482
  result << %(<simpara>#{text_marker}#{item.text}</simpara>)
@@ -485,22 +490,7 @@ module Asciidoctor
485
490
  end
486
491
 
487
492
  def verse node
488
- result = []
489
- result << %(<blockquote#{common_attributes node.id, node.role, node.reftext}>)
490
- result << %(<title>#{node.title}</title>) if node.title?
491
- if (node.attr? 'attribution') || (node.attr? 'citetitle')
492
- result << '<attribution>'
493
- if node.attr? 'attribution'
494
- result << (node.attr 'attribution')
495
- end
496
- if node.attr? 'citetitle'
497
- result << %(<citetitle>#{node.attr 'citetitle'}</citetitle>)
498
- end
499
- result << '</attribution>'
500
- end
501
- result << %(<literallayout>#{node.content}</literallayout>)
502
- result << '</blockquote>'
503
- result * LF
493
+ blockquote_tag(node, (node.has_role? 'epigraph') && 'epigraph') { %(<literallayout>#{node.content}</literallayout>) }
504
494
  end
505
495
 
506
496
  alias video skip
@@ -523,7 +513,8 @@ module Asciidoctor
523
513
  # NOTE technically node.text should be node.reftext, but subs have already been applied to text
524
514
  %(<anchor#{common_attributes node.id, nil, (text = node.text)}/>#{text})
525
515
  else
526
- warn %(asciidoctor: WARNING: unknown anchor type: #{node.type.inspect})
516
+ logger.warn %(unknown anchor type: #{node.type.inspect})
517
+ nil
527
518
  end
528
519
  end
529
520
 
@@ -548,8 +539,8 @@ module Asciidoctor
548
539
  end
549
540
 
550
541
  def inline_image node
551
- width_attribute = (node.attr? 'width') ? %( contentwidth="#{node.attr 'width'}") : nil
552
- depth_attribute = (node.attr? 'height') ? %( contentdepth="#{node.attr 'height'}") : nil
542
+ width_attribute = (node.attr? 'width') ? %( contentwidth="#{node.attr 'width'}") : ''
543
+ depth_attribute = (node.attr? 'height') ? %( contentdepth="#{node.attr 'height'}") : ''
553
544
  %(<inlinemediaobject>
554
545
  <imageobject>
555
546
  <imagedata fileref="#{node.type == 'icon' ? (node.icon_uri node.target) : (node.image_uri node.target)}"#{width_attribute}#{depth_attribute}/>
@@ -606,8 +597,8 @@ module Asciidoctor
606
597
  :monospaced => ['<literal>', '</literal>', false],
607
598
  :emphasis => ['<emphasis>', '</emphasis>', true],
608
599
  :strong => ['<emphasis role="strong">', '</emphasis>', true],
609
- :double => ['&#8220;', '&#8221;', true],
610
- :single => ['&#8216;', '&#8217;', true],
600
+ :double => ['<quote>', '</quote>', true],
601
+ :single => ['<quote>', '</quote>', true],
611
602
  :mark => ['<emphasis role="marked">', '</emphasis>', false],
612
603
  :superscript => ['<superscript>', '</superscript>', false],
613
604
  :subscript => ['<subscript>', '</subscript>', false]
@@ -615,8 +606,7 @@ module Asciidoctor
615
606
 
616
607
  def inline_quoted node
617
608
  if (type = node.type) == :asciimath
618
- if ((defined? ::AsciiMath) || ((defined? @asciimath_available) ? @asciimath_available :
619
- (@asciimath_available = Helpers.require_library 'asciimath', true, :warn)))
609
+ if (@asciimath ||= ((defined? ::AsciiMath) || (Helpers.require_library 'asciimath', true, :warn)).nil? ? :unavailable : :loaded) == :loaded
620
610
  # NOTE fop requires jeuclid to process raw mathml
621
611
  %(<inlineequation>#{(::AsciiMath.parse node.text).to_mathml 'mml:', 'xmlns:mml' => 'http://www.w3.org/1998/Math/MathML'}</inlineequation>)
622
612
  else
@@ -642,7 +632,24 @@ module Asciidoctor
642
632
  end
643
633
  end
644
634
 
645
- def author_element doc, index = nil
635
+ def common_attributes id, role = nil, reftext = nil
636
+ attrs = id ? %( xml:id="#{id}") : ''
637
+ attrs = %(#{attrs} role="#{role}") if role
638
+ if reftext
639
+ if (reftext.include? '<') && ((reftext = reftext.gsub XmlSanitizeRx, '').include? ' ')
640
+ reftext = (reftext.squeeze ' ').strip
641
+ end
642
+ reftext = (reftext.gsub '"', '&quot;') if reftext.include? '"'
643
+ attrs = %(#{attrs} xreflabel="#{reftext}")
644
+ end
645
+ attrs
646
+ end
647
+
648
+ def doctype_declaration root_tag_name
649
+ nil
650
+ end
651
+
652
+ def author_tag doc, index = nil
646
653
  firstname_key = index ? %(firstname_#{index}) : 'firstname'
647
654
  middlename_key = index ? %(middlename_#{index}) : 'middlename'
648
655
  lastname_key = index ? %(lastname_#{index}) : 'lastname'
@@ -661,40 +668,30 @@ module Asciidoctor
661
668
  result * LF
662
669
  end
663
670
 
664
- def common_attributes id, role = nil, reftext = nil
665
- attrs = id ? %( xml:id="#{id}") : ''
666
- attrs = %(#{attrs} role="#{role}") if role
667
- if reftext
668
- if (reftext.include? '<') && ((reftext = reftext.gsub XmlSanitizeRx, '').include? ' ')
669
- reftext = (reftext.squeeze ' ').strip
670
- end
671
- reftext = (reftext.gsub '"', '&quot;') if reftext.include? '"'
672
- attrs = %(#{attrs} xreflabel="#{reftext}")
673
- end
674
- attrs
675
- end
676
-
677
- def doctype_declaration root_tag_name
678
- nil
679
- end
680
-
681
- def document_info_element doc, info_tag_prefix, use_info_tag_prefix = false
682
- info_tag_prefix = nil unless use_info_tag_prefix
671
+ def document_info_tag doc, info_tag_prefix, use_info_tag_prefix = false
672
+ info_tag_prefix = '' unless use_info_tag_prefix
683
673
  result = []
684
674
  result << %(<#{info_tag_prefix}info>)
685
675
  result << document_title_tags(doc.doctitle :partition => true, :use_fallback => true) unless doc.notitle
686
676
  if (date = (doc.attr? 'revdate') ? (doc.attr 'revdate') : ((doc.attr? 'reproducible') ? nil : (doc.attr 'docdate')))
687
677
  result << %(<date>#{date}</date>)
688
678
  end
679
+ if doc.attr? 'copyright'
680
+ CopyrightRx =~ (doc.attr 'copyright')
681
+ result << '<copyright>'
682
+ result << %(<holder>#{$1}</holder>)
683
+ result << %(<year>#{$2}</year>) if $2
684
+ result << '</copyright>'
685
+ end
689
686
  if doc.has_header?
690
687
  if doc.attr? 'author'
691
688
  if (authorcount = (doc.attr 'authorcount').to_i) < 2
692
- result << (author_element doc)
689
+ result << (author_tag doc)
693
690
  result << %(<authorinitials>#{doc.attr 'authorinitials'}</authorinitials>) if doc.attr? 'authorinitials'
694
691
  else
695
692
  result << '<authorgroup>'
696
693
  authorcount.times do |index|
697
- result << (author_element doc, index + 1)
694
+ result << (author_tag doc, index + 1)
698
695
  end
699
696
  result << '</authorgroup>'
700
697
  end
@@ -730,9 +727,11 @@ module Asciidoctor
730
727
  result << '<refmeta>'
731
728
  result << %(<refentrytitle>#{doc.attr 'mantitle'}</refentrytitle>) if doc.attr? 'mantitle'
732
729
  result << %(<manvolnum>#{doc.attr 'manvolnum'}</manvolnum>) if doc.attr? 'manvolnum'
730
+ result << %(<refmiscinfo class="source">#{doc.attr 'mansource', '&#160;'}</refmiscinfo>)
731
+ result << %(<refmiscinfo class="manual">#{doc.attr 'manmanual', '&#160;'}</refmiscinfo>)
733
732
  result << '</refmeta>'
734
733
  result << '<refnamediv>'
735
- result << %(<refname>#{doc.attr 'manname'}</refname>) if doc.attr? 'manname'
734
+ result += (doc.attr 'mannames').map {|n| %(<refname>#{n}</refname>) } if doc.attr? 'mannames'
736
735
  result << %(<refpurpose>#{doc.attr 'manpurpose'}</refpurpose>) if doc.attr? 'manpurpose'
737
736
  result << '</refnamediv>'
738
737
  end
@@ -763,13 +762,13 @@ module Asciidoctor
763
762
  end
764
763
 
765
764
  def title_tag node, optional = true
766
- !optional || node.title? ? %(<title>#{node.title}</title>\n) : nil
765
+ !optional || node.title? ? %(<title>#{node.title}</title>\n) : ''
767
766
  end
768
767
 
769
768
  def cover_tag doc, face, use_placeholder = false
770
769
  if (cover_image = doc.attr %(#{face}-cover-image))
771
- width_attr = nil
772
- depth_attr = nil
770
+ width_attr = ''
771
+ depth_attr = ''
773
772
  if (cover_image.include? ':') && ImageMacroRx =~ cover_image
774
773
  cover_image = doc.image_uri $1
775
774
  unless $2.empty?
@@ -794,5 +793,24 @@ module Asciidoctor
794
793
  %(<cover role="#{face}"/>)
795
794
  end
796
795
  end
796
+
797
+ def blockquote_tag node, tag_name = nil
798
+ if tag_name
799
+ start_tag, end_tag = %(<#{tag_name}), %(</#{tag_name}>)
800
+ else
801
+ start_tag, end_tag = '<blockquote', '</blockquote>'
802
+ end
803
+ result = [%(#{start_tag}#{common_attributes node.id, node.role, node.reftext}>)]
804
+ result << %(<title>#{node.title}</title>) if node.title?
805
+ if (node.attr? 'attribution') || (node.attr? 'citetitle')
806
+ result << '<attribution>'
807
+ result << (node.attr 'attribution') if node.attr? 'attribution'
808
+ result << %(<citetitle>#{node.attr 'citetitle'}</citetitle>) if node.attr? 'citetitle'
809
+ result << '</attribution>'
810
+ end
811
+ result << yield
812
+ result << end_tag
813
+ result * LF
814
+ end
797
815
  end
798
816
  end