asciidoctor 1.5.8 → 2.0.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +162 -17
  3. data/LICENSE +1 -1
  4. data/README-de.adoc +12 -13
  5. data/README-fr.adoc +11 -12
  6. data/README-jp.adoc +11 -12
  7. data/README-zh_CN.adoc +12 -13
  8. data/README.adoc +6 -7
  9. data/asciidoctor.gemspec +19 -24
  10. data/bin/asciidoctor +5 -4
  11. data/data/reference/syntax.adoc +283 -0
  12. data/data/stylesheets/asciidoctor-default.css +56 -52
  13. data/data/stylesheets/coderay-asciidoctor.css +7 -9
  14. data/lib/asciidoctor.rb +171 -232
  15. data/lib/asciidoctor/abstract_block.rb +96 -105
  16. data/lib/asciidoctor/abstract_node.rb +118 -139
  17. data/lib/asciidoctor/attribute_list.rb +10 -14
  18. data/lib/asciidoctor/block.rb +20 -19
  19. data/lib/asciidoctor/callouts.rb +4 -2
  20. data/lib/asciidoctor/cli.rb +3 -2
  21. data/lib/asciidoctor/cli/invoker.rb +14 -21
  22. data/lib/asciidoctor/cli/options.rb +64 -54
  23. data/lib/asciidoctor/converter.rb +357 -185
  24. data/lib/asciidoctor/converter/composite.rb +40 -48
  25. data/lib/asciidoctor/converter/docbook5.rb +604 -640
  26. data/lib/asciidoctor/converter/html5.rb +949 -963
  27. data/lib/asciidoctor/converter/manpage.rb +569 -548
  28. data/lib/asciidoctor/converter/template.rb +231 -272
  29. data/lib/asciidoctor/core_ext.rb +5 -18
  30. data/lib/asciidoctor/core_ext/float/truncate.rb +19 -0
  31. data/lib/asciidoctor/core_ext/match_data/names.rb +7 -0
  32. data/lib/asciidoctor/core_ext/nil_or_empty.rb +1 -0
  33. data/lib/asciidoctor/core_ext/regexp/is_match.rb +4 -2
  34. data/lib/asciidoctor/document.rb +399 -377
  35. data/lib/asciidoctor/extensions.rb +72 -140
  36. data/lib/asciidoctor/helpers.rb +122 -83
  37. data/lib/asciidoctor/inline.rb +5 -1
  38. data/lib/asciidoctor/list.rb +13 -11
  39. data/lib/asciidoctor/logging.rb +17 -16
  40. data/lib/asciidoctor/parser.rb +390 -423
  41. data/lib/asciidoctor/path_resolver.rb +10 -5
  42. data/lib/asciidoctor/reader.rb +286 -263
  43. data/lib/asciidoctor/rouge_ext.rb +39 -0
  44. data/lib/asciidoctor/section.rb +9 -8
  45. data/lib/asciidoctor/stylesheets.rb +19 -37
  46. data/lib/asciidoctor/substitutors.rb +364 -509
  47. data/lib/asciidoctor/syntax_highlighter.rb +238 -0
  48. data/lib/asciidoctor/syntax_highlighter/coderay.rb +87 -0
  49. data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +26 -0
  50. data/lib/asciidoctor/syntax_highlighter/html_pipeline.rb +10 -0
  51. data/lib/asciidoctor/syntax_highlighter/prettify.rb +27 -0
  52. data/lib/asciidoctor/syntax_highlighter/pygments.rb +149 -0
  53. data/lib/asciidoctor/syntax_highlighter/rouge.rb +129 -0
  54. data/lib/asciidoctor/table.rb +73 -66
  55. data/lib/asciidoctor/timings.rb +4 -2
  56. data/lib/asciidoctor/version.rb +2 -1
  57. data/lib/asciidoctor/writer.rb +30 -0
  58. data/man/asciidoctor.1 +19 -15
  59. data/man/asciidoctor.adoc +14 -12
  60. metadata +69 -216
  61. data/CONTRIBUTING.adoc +0 -185
  62. data/Gemfile +0 -60
  63. data/Rakefile +0 -129
  64. data/bin/asciidoctor-safe +0 -15
  65. data/features/open_block.feature +0 -92
  66. data/features/pass_block.feature +0 -66
  67. data/features/step_definitions.rb +0 -49
  68. data/features/text_formatting.feature +0 -57
  69. data/features/xref.feature +0 -1039
  70. data/lib/asciidoctor/converter/base.rb +0 -59
  71. data/lib/asciidoctor/converter/docbook45.rb +0 -93
  72. data/lib/asciidoctor/converter/factory.rb +0 -226
  73. data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +0 -6
  74. data/lib/asciidoctor/core_ext/1.8.7/concurrent/hash.rb +0 -5
  75. data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +0 -4
  76. data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +0 -6
  77. data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +0 -5
  78. data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +0 -6
  79. data/lib/asciidoctor/core_ext/1.8.7/string/limit_bytesize.rb +0 -29
  80. data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +0 -6
  81. data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +0 -6
  82. data/lib/asciidoctor/core_ext/string/limit_bytesize.rb +0 -10
  83. data/test/api_test.rb +0 -1240
  84. data/test/attribute_list_test.rb +0 -242
  85. data/test/attributes_test.rb +0 -1623
  86. data/test/blocks_test.rb +0 -3870
  87. data/test/converter_test.rb +0 -470
  88. data/test/document_test.rb +0 -1853
  89. data/test/extensions_test.rb +0 -1560
  90. data/test/fixtures/asciidoc_index.txt +0 -521
  91. data/test/fixtures/basic-docinfo-footer.html +0 -6
  92. data/test/fixtures/basic-docinfo-footer.xml +0 -8
  93. data/test/fixtures/basic-docinfo.html +0 -1
  94. data/test/fixtures/basic-docinfo.xml +0 -4
  95. data/test/fixtures/basic.asciidoc +0 -5
  96. data/test/fixtures/chapter-a.adoc +0 -3
  97. data/test/fixtures/child-include.adoc +0 -5
  98. data/test/fixtures/circle.svg +0 -9
  99. data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +0 -6
  100. data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +0 -6
  101. data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +0 -1
  102. data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +0 -3
  103. data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +0 -5
  104. data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +0 -6
  105. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +0 -3
  106. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +0 -5
  107. data/test/fixtures/custom-docinfodir/basic-docinfo.html +0 -1
  108. data/test/fixtures/custom-docinfodir/docinfo.html +0 -1
  109. data/test/fixtures/docinfo-footer.html +0 -1
  110. data/test/fixtures/docinfo-footer.xml +0 -9
  111. data/test/fixtures/docinfo.html +0 -1
  112. data/test/fixtures/docinfo.xml +0 -3
  113. data/test/fixtures/doctime-localtime.adoc +0 -2
  114. data/test/fixtures/dot.gif +0 -0
  115. data/test/fixtures/encoding.asciidoc +0 -13
  116. data/test/fixtures/file-with-missing-include.adoc +0 -1
  117. data/test/fixtures/grandchild-include.adoc +0 -3
  118. data/test/fixtures/hello-asciidoctor.pdf +0 -69
  119. data/test/fixtures/include-file.asciidoc +0 -24
  120. data/test/fixtures/include-file.jsx +0 -8
  121. data/test/fixtures/include-file.ml +0 -3
  122. data/test/fixtures/include-file.xml +0 -5
  123. data/test/fixtures/lists.adoc +0 -96
  124. data/test/fixtures/master.adoc +0 -5
  125. data/test/fixtures/mismatched-end-tag.adoc +0 -7
  126. data/test/fixtures/other-chapters.adoc +0 -11
  127. data/test/fixtures/outer-include.adoc +0 -5
  128. data/test/fixtures/parent-include-restricted.adoc +0 -5
  129. data/test/fixtures/parent-include.adoc +0 -5
  130. data/test/fixtures/sample.asciidoc +0 -30
  131. data/test/fixtures/section-a.adoc +0 -4
  132. data/test/fixtures/stylesheets/custom.css +0 -3
  133. data/test/fixtures/subdir/index.adoc +0 -3
  134. data/test/fixtures/subdir/inner-include.adoc +0 -3
  135. data/test/fixtures/subdir/middle-include.adoc +0 -5
  136. data/test/fixtures/subs-docinfo.html +0 -2
  137. data/test/fixtures/subs.adoc +0 -6
  138. data/test/fixtures/tagged-class-enclosed.rb +0 -25
  139. data/test/fixtures/tagged-class.rb +0 -23
  140. data/test/fixtures/tip.gif +0 -0
  141. data/test/fixtures/unclosed-tag.adoc +0 -3
  142. data/test/fixtures/unexpected-end-tag.adoc +0 -4
  143. data/test/invoker_test.rb +0 -745
  144. data/test/links_test.rb +0 -855
  145. data/test/lists_test.rb +0 -5151
  146. data/test/logger_test.rb +0 -211
  147. data/test/manpage_test.rb +0 -660
  148. data/test/options_test.rb +0 -262
  149. data/test/paragraphs_test.rb +0 -562
  150. data/test/parser_test.rb +0 -742
  151. data/test/paths_test.rb +0 -395
  152. data/test/preamble_test.rb +0 -173
  153. data/test/reader_test.rb +0 -2161
  154. data/test/sections_test.rb +0 -3575
  155. data/test/substitutions_test.rb +0 -2066
  156. data/test/tables_test.rb +0 -2036
  157. data/test/test_helper.rb +0 -447
  158. data/test/text_test.rb +0 -309
@@ -1,55 +1,47 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
2
  module Asciidoctor
3
- # A {Converter} implementation that delegates to the chain of {Converter}
4
- # objects passed to the constructor. Selects the first {Converter} that
5
- # identifies itself as the handler for a given transform.
6
- class Converter::CompositeConverter < Converter::Base
3
+ # A {Converter} implementation that delegates to the chain of {Converter}
4
+ # objects passed to the constructor. Selects the first {Converter} that
5
+ # identifies itself as the handler for a given transform.
6
+ class Converter::CompositeConverter < Converter::Base
7
+ # Get the Array of Converter objects in the chain
8
+ attr_reader :converters
7
9
 
8
- # Get the Array of Converter objects in the chain
9
- attr_reader :converters
10
-
11
- def initialize backend, *converters
12
- @backend = backend
13
- (@converters = converters.flatten.compact).each do |converter|
14
- converter.composed self if converter.respond_to? :composed
15
- end
16
- @converter_map = {}
17
- end
18
-
19
- # Public: Delegates to the first converter that identifies itself as the
20
- # handler for the given transform. The optional Hash is passed as the last
21
- # option to the delegate's convert method.
22
- #
23
- # node - the AbstractNode to convert
24
- # transform - the optional String transform, or the name of the node if no
25
- # transform is specified. (default: nil)
26
- # opts - an optional Hash that is passed to the delegate's convert method. (default: {})
27
- #
28
- # Returns the String result returned from the delegate's convert method
29
- def convert node, transform = nil, opts = {}
30
- transform ||= node.node_name
31
- (converter_for transform).convert node, transform, opts
32
- end
10
+ def initialize backend, *converters, backend_traits_source: nil
11
+ @backend = backend
12
+ (@converters = converters).each {|converter| converter.composed self if converter.respond_to? :composed }
13
+ init_backend_traits backend_traits_source.backend_traits if backend_traits_source
14
+ @converter_cache = ::Hash.new {|hash, key| hash[key] = find_converter key }
15
+ end
33
16
 
34
- # Alias for backward compatibility.
35
- alias convert_with_options convert
17
+ # Public: Delegates to the first converter that identifies itself as the
18
+ # handler for the given transform. The optional Hash is passed as the last
19
+ # option to the delegate's convert method.
20
+ #
21
+ # node - the AbstractNode to convert
22
+ # transform - the optional String transform, or the name of the node if no
23
+ # transform is specified. (default: nil)
24
+ # opts - an optional Hash that is passed to the delegate's convert method. (default: nil)
25
+ #
26
+ # Returns the String result returned from the delegate's convert method
27
+ def convert node, transform = nil, opts = nil
28
+ (converter_for transform ||= node.node_name).convert node, transform, opts
29
+ end
36
30
 
37
- # Public: Retrieve the converter for the specified transform.
38
- #
39
- # Returns the matching [Converter] object
40
- def converter_for transform
41
- @converter_map[transform] ||= (find_converter transform)
42
- end
31
+ # Public: Retrieve the converter for the specified transform.
32
+ #
33
+ # Returns the matching [Converter] object
34
+ def converter_for transform
35
+ @converter_cache[transform]
36
+ end
43
37
 
44
- # Internal: Find the converter for the specified transform.
45
- # Raise an exception if no converter is found.
46
- #
47
- # Returns the matching [Converter] object
48
- def find_converter transform
49
- @converters.each do |candidate|
50
- return candidate if candidate.handles? transform
51
- end
52
- raise %(Could not find a converter to handle transform: #{transform})
53
- end
38
+ # Public: Find the converter for the specified transform.
39
+ # Raise an exception if no converter is found.
40
+ #
41
+ # Returns the matching [Converter] object
42
+ def find_converter transform
43
+ @converters.each {|candidate| return candidate if candidate.handles? transform }
44
+ raise %(Could not find a converter to handle transform: #{transform})
54
45
  end
55
46
  end
47
+ end
@@ -1,815 +1,779 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
2
  module Asciidoctor
3
- # A built-in {Converter} implementation that generates DocBook 5 output
4
- # similar to the docbook45 backend from AsciiDoc Python, but migrated to the
5
- # DocBook 5 specification.
6
- class Converter::DocBook5Converter < Converter::BuiltIn
7
- CopyrightRx = /^(.+?)(?: ((?:\d{4}\-)?\d{4}))?$/
8
- ImageMacroRx = /^image::?(.+?)\[(.*?)\]$/
9
-
10
- def document node
11
- result = []
12
- if (root_tag_name = node.doctype) == 'manpage'
13
- root_tag_name = 'refentry'
14
- end
15
- result << '<?xml version="1.0" encoding="UTF-8"?>'
16
- if (doctype_line = doctype_declaration root_tag_name)
17
- result << doctype_line
18
- end
19
- if node.attr? 'toc'
20
- if node.attr? 'toclevels'
21
- result << %(<?asciidoc-toc maxdepth="#{node.attr 'toclevels'}"?>)
22
- else
23
- result << '<?asciidoc-toc?>'
24
- end
25
- end
26
- if node.attr? 'sectnums'
27
- if node.attr? 'sectnumlevels'
28
- result << %(<?asciidoc-numbered maxdepth="#{node.attr 'sectnumlevels'}"?>)
29
- else
30
- result << '<?asciidoc-numbered?>'
31
- end
3
+ # A built-in {Converter} implementation that generates DocBook 5 output. The output is inspired by the output produced
4
+ # by the docbook45 backend from AsciiDoc Python, except it has been migrated to the DocBook 5 specification.
5
+ class Converter::DocBook5Converter < Converter::Base
6
+ register_for 'docbook5'
7
+
8
+ # default represents variablelist
9
+ (DLIST_TAGS = {
10
+ 'qanda' => { list: 'qandaset', entry: 'qandaentry', label: 'question', term: 'simpara', item: 'answer' },
11
+ 'glossary' => { list: nil, entry: 'glossentry', term: 'glossterm', item: 'glossdef' },
12
+ }).default = { list: 'variablelist', entry: 'varlistentry', term: 'term', item: 'listitem' }
13
+
14
+ (QUOTE_TAGS = {
15
+ monospaced: ['<literal>', '</literal>'],
16
+ emphasis: ['<emphasis>', '</emphasis>', true],
17
+ strong: ['<emphasis role="strong">', '</emphasis>', true],
18
+ double: ['<quote>', '</quote>', true],
19
+ single: ['<quote>', '</quote>', true],
20
+ mark: ['<emphasis role="marked">', '</emphasis>'],
21
+ superscript: ['<superscript>', '</superscript>'],
22
+ subscript: ['<subscript>', '</subscript>'],
23
+ }).default = ['', '', true]
24
+
25
+ MANPAGE_SECTION_TAGS = { 'section' => 'refsection', 'synopsis' => 'refsynopsisdiv' }
26
+ TABLE_PI_NAMES = ['dbhtml', 'dbfo', 'dblatex']
27
+
28
+ CopyrightRx = /^(.+?)(?: ((?:\d{4}\-)?\d{4}))?$/
29
+ ImageMacroRx = /^image::?(.+?)\[(.*?)\]$/
30
+
31
+ def initialize backend, opts = {}
32
+ @backend = backend
33
+ init_backend_traits basebackend: 'docbook', filetype: 'xml', outfilesuffix: '.xml', supports_templates: true
34
+ end
35
+
36
+ def document node
37
+ result = ['<?xml version="1.0" encoding="UTF-8"?>']
38
+ if node.attr? 'toc'
39
+ if node.attr? 'toclevels'
40
+ result << %(<?asciidoc-toc maxdepth="#{node.attr 'toclevels'}"?>)
41
+ else
42
+ result << '<?asciidoc-toc?>'
32
43
  end
33
- lang_attribute = (node.attr? 'nolang') ? '' : %( #{lang_attribute_name}="#{node.attr 'lang', 'en'}")
34
- result << %(<#{root_tag_name}#{document_ns_attributes node}#{lang_attribute}>)
35
- result << (document_info_tag node, root_tag_name) unless node.noheader
36
- result << node.content if node.blocks?
37
- unless (footer_docinfo = node.docinfo :footer).empty?
38
- result << footer_docinfo
44
+ end
45
+ if node.attr? 'sectnums'
46
+ if node.attr? 'sectnumlevels'
47
+ result << %(<?asciidoc-numbered maxdepth="#{node.attr 'sectnumlevels'}"?>)
48
+ else
49
+ result << '<?asciidoc-numbered?>'
39
50
  end
40
- result << %(</#{root_tag_name}>)
41
- result.join LF
42
51
  end
52
+ lang_attribute = (node.attr? 'nolang') ? '' : %( xml:lang="#{node.attr 'lang', 'en'}")
53
+ if (root_tag_name = node.doctype) == 'manpage'
54
+ root_tag_name = 'refentry'
55
+ end
56
+ result << %(<#{root_tag_name} xmlns="http://docbook.org/ns/docbook" xmlns:xl="http://www.w3.org/1999/xlink" version="5.0"#{lang_attribute}#{_common_attributes node.id}>)
57
+ result << (_document_info_tag node) unless node.noheader
58
+ unless (docinfo_content = node.docinfo :header).empty?
59
+ result << docinfo_content
60
+ end
61
+ result << node.content if node.blocks?
62
+ unless (docinfo_content = node.docinfo :footer).empty?
63
+ result << docinfo_content
64
+ end
65
+ result << %(</#{root_tag_name}>)
66
+ result.join LF
67
+ end
43
68
 
44
- alias embedded content
45
-
46
- MANPAGE_SECTION_TAGS = { 'section' => 'refsection', 'synopsis' => 'refsynopsisdiv' }
69
+ alias embedded _content_only
47
70
 
48
- def section node
49
- if node.document.doctype == 'manpage'
50
- tag_name = MANPAGE_SECTION_TAGS[tag_name = node.sectname] || tag_name
51
- else
52
- tag_name = node.sectname
53
- end
54
- title_el = node.special && (node.option? 'untitled') ? '' : %(<title>#{node.title}</title>\n)
55
- %(<#{tag_name}#{common_attributes node.id, node.role, node.reftext}>
71
+ def section node
72
+ if node.document.doctype == 'manpage'
73
+ tag_name = MANPAGE_SECTION_TAGS[tag_name = node.sectname] || tag_name
74
+ else
75
+ tag_name = node.sectname
76
+ end
77
+ title_el = node.special && (node.option? 'untitled') ? '' : %(<title>#{node.title}</title>\n)
78
+ %(<#{tag_name}#{_common_attributes node.id, node.role, node.reftext}>
56
79
  #{title_el}#{node.content}
57
80
  </#{tag_name}>)
58
- end
81
+ end
59
82
 
60
- def admonition node
61
- %(<#{tag_name = node.attr 'name'}#{common_attributes node.id, node.role, node.reftext}>
62
- #{title_tag node}#{resolve_content node}
83
+ def admonition node
84
+ %(<#{tag_name = node.attr 'name'}#{_common_attributes node.id, node.role, node.reftext}>
85
+ #{_title_tag node}#{_enclose_content node}
63
86
  </#{tag_name}>)
64
- end
87
+ end
65
88
 
66
- alias audio skip
89
+ alias audio _skip
67
90
 
68
- def colist node
69
- result = []
70
- result << %(<calloutlist#{common_attributes node.id, node.role, node.reftext}>)
71
- result << %(<title>#{node.title}</title>) if node.title?
72
- node.items.each do |item|
73
- result << %(<callout arearefs="#{item.attr 'coids'}">)
74
- result << %(<para>#{item.text}</para>)
75
- result << item.content if item.blocks?
76
- result << '</callout>'
77
- end
78
- result << %(</calloutlist>)
79
- result.join LF
91
+ def colist node
92
+ result = []
93
+ result << %(<calloutlist#{_common_attributes node.id, node.role, node.reftext}>)
94
+ result << %(<title>#{node.title}</title>) if node.title?
95
+ node.items.each do |item|
96
+ result << %(<callout arearefs="#{item.attr 'coids'}">)
97
+ result << %(<para>#{item.text}</para>)
98
+ result << item.content if item.blocks?
99
+ result << '</callout>'
80
100
  end
101
+ result << %(</calloutlist>)
102
+ result.join LF
103
+ end
81
104
 
82
- (DLIST_TAGS = {
83
- 'qanda' => {
84
- :list => 'qandaset',
85
- :entry => 'qandaentry',
86
- :label => 'question',
87
- :term => 'simpara',
88
- :item => 'answer'
89
- },
90
- 'glossary' => {
91
- :list => nil,
92
- :entry => 'glossentry',
93
- :term => 'glossterm',
94
- :item => 'glossdef'
95
- }
96
- }).default = { # default is variable
97
- :list => 'variablelist',
98
- :entry => 'varlistentry',
99
- :term => 'term',
100
- :item => 'listitem'
101
- }
102
-
103
- def dlist node
104
- result = []
105
- if node.style == 'horizontal'
106
- result << %(<#{tag_name = node.title? ? 'table' : 'informaltable'}#{common_attributes node.id, node.role, node.reftext} tabstyle="horizontal" frame="none" colsep="0" rowsep="0">
107
- #{title_tag node}<tgroup cols="2">
105
+ def dlist node
106
+ result = []
107
+ if node.style == 'horizontal'
108
+ result << %(<#{tag_name = node.title? ? 'table' : 'informaltable'}#{_common_attributes node.id, node.role, node.reftext} tabstyle="horizontal" frame="none" colsep="0" rowsep="0">
109
+ #{_title_tag node}<tgroup cols="2">
108
110
  <colspec colwidth="#{node.attr 'labelwidth', 15}*"/>
109
111
  <colspec colwidth="#{node.attr 'itemwidth', 85}*"/>
110
112
  <tbody valign="top">)
111
- node.items.each do |terms, dd|
112
- result << %(<row>
113
+ node.items.each do |terms, dd|
114
+ result << %(<row>
113
115
  <entry>)
114
- [*terms].each do |dt|
115
- result << %(<simpara>#{dt.text}</simpara>)
116
- end
117
- result << %(</entry>
116
+ terms.each {|dt| result << %(<simpara>#{dt.text}</simpara>) }
117
+ result << %(</entry>
118
118
  <entry>)
119
- if dd
120
- result << %(<simpara>#{dd.text}</simpara>) if dd.text?
121
- result << dd.content if dd.blocks?
122
- end
123
- result << %(</entry>
124
- </row>)
119
+ if dd
120
+ result << %(<simpara>#{dd.text}</simpara>) if dd.text?
121
+ result << dd.content if dd.blocks?
125
122
  end
126
- result << %(</tbody>
123
+ result << %(</entry>
124
+ </row>)
125
+ end
126
+ result << %(</tbody>
127
127
  </tgroup>
128
128
  </#{tag_name}>)
129
- else
130
- tags = DLIST_TAGS[node.style]
131
- list_tag = tags[:list]
132
- entry_tag = tags[:entry]
133
- label_tag = tags[:label]
134
- term_tag = tags[:term]
135
- item_tag = tags[:item]
136
- if list_tag
137
- result << %(<#{list_tag}#{common_attributes node.id, node.role, node.reftext}>)
138
- result << %(<title>#{node.title}</title>) if node.title?
139
- end
140
-
141
- node.items.each do |terms, dd|
142
- result << %(<#{entry_tag}>)
143
- result << %(<#{label_tag}>) if label_tag
144
-
145
- [*terms].each do |dt|
146
- result << %(<#{term_tag}>#{dt.text}</#{term_tag}>)
147
- end
129
+ else
130
+ tags = DLIST_TAGS[node.style]
131
+ list_tag = tags[:list]
132
+ entry_tag = tags[:entry]
133
+ label_tag = tags[:label]
134
+ term_tag = tags[:term]
135
+ item_tag = tags[:item]
136
+ if list_tag
137
+ result << %(<#{list_tag}#{_common_attributes node.id, node.role, node.reftext}>)
138
+ result << %(<title>#{node.title}</title>) if node.title?
139
+ end
148
140
 
149
- result << %(</#{label_tag}>) if label_tag
150
- result << %(<#{item_tag}>)
151
- if dd
152
- result << %(<simpara>#{dd.text}</simpara>) if dd.text?
153
- result << dd.content if dd.blocks?
154
- end
155
- result << %(</#{item_tag}>)
156
- result << %(</#{entry_tag}>)
141
+ node.items.each do |terms, dd|
142
+ result << %(<#{entry_tag}>)
143
+ result << %(<#{label_tag}>) if label_tag
144
+ terms.each {|dt| result << %(<#{term_tag}>#{dt.text}</#{term_tag}>) }
145
+ result << %(</#{label_tag}>) if label_tag
146
+ result << %(<#{item_tag}>)
147
+ if dd
148
+ result << %(<simpara>#{dd.text}</simpara>) if dd.text?
149
+ result << dd.content if dd.blocks?
157
150
  end
158
-
159
- result << %(</#{list_tag}>) if list_tag
151
+ result << %(</#{item_tag}>)
152
+ result << %(</#{entry_tag}>)
160
153
  end
161
154
 
162
- result.join LF
155
+ result << %(</#{list_tag}>) if list_tag
163
156
  end
164
157
 
165
- def example node
166
- if node.title?
167
- %(<example#{common_attributes node.id, node.role, node.reftext}>
158
+ result.join LF
159
+ end
160
+
161
+ def example node
162
+ if node.title?
163
+ %(<example#{_common_attributes node.id, node.role, node.reftext}>
168
164
  <title>#{node.title}</title>
169
- #{resolve_content node}
165
+ #{_enclose_content node}
170
166
  </example>)
171
- else
172
- %(<informalexample#{common_attributes node.id, node.role, node.reftext}>
173
- #{resolve_content node}
167
+ else
168
+ %(<informalexample#{_common_attributes node.id, node.role, node.reftext}>
169
+ #{_enclose_content node}
174
170
  </informalexample>)
175
- end
176
171
  end
172
+ end
177
173
 
178
- def floating_title node
179
- %(<bridgehead#{common_attributes node.id, node.role, node.reftext} renderas="sect#{node.level}">#{node.title}</bridgehead>)
180
- end
174
+ def floating_title node
175
+ %(<bridgehead#{_common_attributes node.id, node.role, node.reftext} renderas="sect#{node.level}">#{node.title}</bridgehead>)
176
+ end
181
177
 
182
- def image node
183
- # NOTE according to the DocBook spec, content area, scaling, and scaling to fit are mutually exclusive
184
- # See http://tdg.docbook.org/tdg/4.5/imagedata-x.html#d0e79635
185
- if node.attr? 'scaledwidth'
186
- width_attribute = %( width="#{node.attr 'scaledwidth'}")
187
- depth_attribute = ''
188
- scale_attribute = ''
189
- elsif node.attr? 'scale'
190
- # 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'}") : ''
192
- #depth_attribute = (node.attr? 'height') ? %( depth="#{node.attr 'height'}") : ''
193
- scale_attribute = %( scale="#{node.attr 'scale'}")
194
- else
195
- width_attribute = (node.attr? 'width') ? %( contentwidth="#{node.attr 'width'}") : ''
196
- depth_attribute = (node.attr? 'height') ? %( contentdepth="#{node.attr 'height'}") : ''
197
- scale_attribute = ''
198
- end
199
- align_attribute = (node.attr? 'align') ? %( align="#{node.attr 'align'}") : ''
178
+ def image node
179
+ # NOTE according to the DocBook spec, content area, scaling, and scaling to fit are mutually exclusive
180
+ # See http://tdg.docbook.org/tdg/4.5/imagedata-x.html#d0e79635
181
+ if node.attr? 'scaledwidth'
182
+ width_attribute = %( width="#{node.attr 'scaledwidth'}")
183
+ depth_attribute = ''
184
+ scale_attribute = ''
185
+ elsif node.attr? 'scale'
186
+ # QUESTION should we set the viewport using width and depth? (the scaled image would be contained within this box)
187
+ #width_attribute = (node.attr? 'width') ? %( width="#{node.attr 'width'}") : ''
188
+ #depth_attribute = (node.attr? 'height') ? %( depth="#{node.attr 'height'}") : ''
189
+ scale_attribute = %( scale="#{node.attr 'scale'}")
190
+ else
191
+ width_attribute = (node.attr? 'width') ? %( contentwidth="#{node.attr 'width'}") : ''
192
+ depth_attribute = (node.attr? 'height') ? %( contentdepth="#{node.attr 'height'}") : ''
193
+ scale_attribute = ''
194
+ end
195
+ align_attribute = (node.attr? 'align') ? %( align="#{node.attr 'align'}") : ''
200
196
 
201
- mediaobject = %(<mediaobject>
197
+ mediaobject = %(<mediaobject>
202
198
  <imageobject>
203
199
  <imagedata fileref="#{node.image_uri(node.attr 'target')}"#{width_attribute}#{depth_attribute}#{scale_attribute}#{align_attribute}/>
204
200
  </imageobject>
205
201
  <textobject><phrase>#{node.alt}</phrase></textobject>
206
202
  </mediaobject>)
207
203
 
208
- if node.title?
209
- %(<figure#{common_attributes node.id, node.role, node.reftext}>
204
+ if node.title?
205
+ %(<figure#{_common_attributes node.id, node.role, node.reftext}>
210
206
  <title>#{node.title}</title>
211
207
  #{mediaobject}
212
208
  </figure>)
213
- else
214
- %(<informalfigure#{common_attributes node.id, node.role, node.reftext}>
209
+ else
210
+ %(<informalfigure#{_common_attributes node.id, node.role, node.reftext}>
215
211
  #{mediaobject}
216
212
  </informalfigure>)
217
- end
218
213
  end
214
+ end
219
215
 
220
- def listing node
221
- informal = !node.title?
222
- listing_attributes = (common_attributes node.id, node.role, node.reftext)
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>)
216
+ def listing node
217
+ informal = !node.title?
218
+ common_attrs = _common_attributes node.id, node.role, node.reftext
219
+ if node.style == 'source'
220
+ if (attrs = node.attributes).key? 'linenums'
221
+ numbering_attrs = (attrs.key? 'start') ? %( linenumbering="numbered" startinglinenumber="#{attrs['start'].to_i}") : ' linenumbering="numbered"'
234
222
  else
235
- listing_content = %(<screen#{informal ? listing_attributes : ''}>#{node.content}</screen>)
223
+ numbering_attrs = ' linenumbering="unnumbered"'
236
224
  end
237
- if informal
238
- listing_content
225
+ if attrs.key? 'language'
226
+ wrapped_content = %(<programlisting#{informal ? common_attrs : ''} language="#{attrs['language']}"#{numbering_attrs}>#{node.content}</programlisting>)
239
227
  else
240
- %(<formalpara#{listing_attributes}>
228
+ wrapped_content = %(<screen#{informal ? common_attrs : ''}#{numbering_attrs}>#{node.content}</screen>)
229
+ end
230
+ else
231
+ wrapped_content = %(<screen#{informal ? common_attrs : ''}>#{node.content}</screen>)
232
+ end
233
+ informal ? wrapped_content : %(<formalpara#{common_attrs}>
241
234
  <title>#{node.title}</title>
242
235
  <para>
243
- #{listing_content}
236
+ #{wrapped_content}
244
237
  </para>
245
238
  </formalpara>)
246
- end
247
- end
239
+ end
248
240
 
249
- def literal node
250
- if node.title?
251
- %(<formalpara#{common_attributes node.id, node.role, node.reftext}>
241
+ def literal node
242
+ if node.title?
243
+ %(<formalpara#{_common_attributes node.id, node.role, node.reftext}>
252
244
  <title>#{node.title}</title>
253
245
  <para>
254
246
  <literallayout class="monospaced">#{node.content}</literallayout>
255
247
  </para>
256
248
  </formalpara>)
257
- else
258
- %(<literallayout#{common_attributes node.id, node.role, node.reftext} class="monospaced">#{node.content}</literallayout>)
259
- end
249
+ else
250
+ %(<literallayout#{_common_attributes node.id, node.role, node.reftext} class="monospaced">#{node.content}</literallayout>)
260
251
  end
252
+ end
261
253
 
262
- def stem node
263
- if (idx = node.subs.index :specialcharacters)
264
- node.subs.delete_at idx
265
- equation = node.content
266
- idx > 0 ? (node.subs.insert idx, :specialcharacters) : (node.subs.unshift :specialcharacters)
267
- else
268
- equation = node.content
269
- end
270
- if node.style == 'asciimath'
271
- if (@asciimath ||= ((defined? ::AsciiMath) || (Helpers.require_library 'asciimath', true, :warn)).nil? ? :unavailable : :loaded) == :loaded
272
- # NOTE fop requires jeuclid to process raw mathml
273
- equation_data = (::AsciiMath.parse equation).to_mathml 'mml:', 'xmlns:mml' => 'http://www.w3.org/1998/Math/MathML'
274
- else
275
- equation_data = %(<mathphrase><![CDATA[#{equation}]]></mathphrase>)
276
- end
277
- else
278
- # unhandled math; pass source to alt and required mathphrase element; dblatex will process alt as LaTeX math
279
- equation_data = %(<alt><![CDATA[#{equation}]]></alt>
254
+ alias pass _content_only
255
+
256
+ def stem node
257
+ if (idx = node.subs.index :specialcharacters)
258
+ node.subs.delete_at idx
259
+ equation = node.content || ''
260
+ idx > 0 ? (node.subs.insert idx, :specialcharacters) : (node.subs.unshift :specialcharacters)
261
+ else
262
+ equation = node.content || ''
263
+ end
264
+ if node.style == 'asciimath'
265
+ # NOTE fop requires jeuclid to process mathml markup
266
+ equation_data = _asciimath_available? ? ((::AsciiMath.parse equation).to_mathml 'mml:', 'xmlns:mml' => 'http://www.w3.org/1998/Math/MathML') : %(<mathphrase><![CDATA[#{equation}]]></mathphrase>)
267
+ else
268
+ # unhandled math; pass source to alt and required mathphrase element; dblatex will process alt as LaTeX math
269
+ equation_data = %(<alt><![CDATA[#{equation}]]></alt>
280
270
  <mathphrase><![CDATA[#{equation}]]></mathphrase>)
281
- end
282
- if node.title?
283
- %(<equation#{common_attributes node.id, node.role, node.reftext}>
271
+ end
272
+ if node.title?
273
+ %(<equation#{_common_attributes node.id, node.role, node.reftext}>
284
274
  <title>#{node.title}</title>
285
275
  #{equation_data}
286
276
  </equation>)
287
- else
288
- # WARNING dblatex displays the <informalequation> element inline instead of block as documented (except w/ mathml)
289
- %(<informalequation#{common_attributes node.id, node.role, node.reftext}>
277
+ else
278
+ # WARNING dblatex displays the <informalequation> element inline instead of block as documented (except w/ mathml)
279
+ %(<informalequation#{_common_attributes node.id, node.role, node.reftext}>
290
280
  #{equation_data}
291
281
  </informalequation>)
292
- end
293
282
  end
283
+ end
294
284
 
295
- def olist node
296
- result = []
297
- num_attribute = node.style ? %( numeration="#{node.style}") : ''
298
- start_attribute = (node.attr? 'start') ? %( startingnumber="#{node.attr 'start'}") : ''
299
- result << %(<orderedlist#{common_attributes node.id, node.role, node.reftext}#{num_attribute}#{start_attribute}>)
300
- result << %(<title>#{node.title}</title>) if node.title?
301
- node.items.each do |item|
302
- result << '<listitem>'
303
- result << %(<simpara>#{item.text}</simpara>)
304
- result << item.content if item.blocks?
305
- result << '</listitem>'
306
- end
307
- result << %(</orderedlist>)
308
- result.join LF
309
- end
285
+ def olist node
286
+ result = []
287
+ num_attribute = node.style ? %( numeration="#{node.style}") : ''
288
+ start_attribute = (node.attr? 'start') ? %( startingnumber="#{node.attr 'start'}") : ''
289
+ result << %(<orderedlist#{_common_attributes node.id, node.role, node.reftext}#{num_attribute}#{start_attribute}>)
290
+ result << %(<title>#{node.title}</title>) if node.title?
291
+ node.items.each do |item|
292
+ result << %(<listitem#{_common_attributes item.id, item.role}>)
293
+ result << %(<simpara>#{item.text}</simpara>)
294
+ result << item.content if item.blocks?
295
+ result << '</listitem>'
296
+ end
297
+ result << %(</orderedlist>)
298
+ result.join LF
299
+ end
310
300
 
311
- def open node
312
- case node.style
313
- when 'abstract'
314
- if node.parent == node.document && node.document.doctype == 'book'
315
- logger.warn 'abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
316
- ''
317
- else
318
- %(<abstract>
319
- #{title_tag node}#{resolve_content node}
301
+ def open node
302
+ case node.style
303
+ when 'abstract'
304
+ if node.parent == node.document && node.document.doctype == 'book'
305
+ logger.warn 'abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
306
+ ''
307
+ else
308
+ %(<abstract>
309
+ #{_title_tag node}#{_enclose_content node}
320
310
  </abstract>)
321
- end
322
- when 'partintro'
323
- unless node.level == 0 && node.parent.context == :section && node.document.doctype == 'book'
324
- logger.error 'partintro block can only be used when doctype is book and must be a child of a book part. Excluding block content.'
325
- ''
326
- else
327
- %(<partintro#{common_attributes node.id, node.role, node.reftext}>
328
- #{title_tag node}#{resolve_content node}
329
- </partintro>)
330
- end
311
+ end
312
+ when 'partintro'
313
+ unless node.level == 0 && node.parent.context == :section && node.document.doctype == 'book'
314
+ logger.error 'partintro block can only be used when doctype is book and must be a child of a book part. Excluding block content.'
315
+ ''
331
316
  else
332
- reftext = node.reftext if (id = node.id)
333
- role = node.role
334
- if node.title?
335
- %(<formalpara#{common_attributes id, role, reftext}>
317
+ %(<partintro#{_common_attributes node.id, node.role, node.reftext}>
318
+ #{_title_tag node}#{_enclose_content node}
319
+ </partintro>)
320
+ end
321
+ else
322
+ reftext = node.reftext if (id = node.id)
323
+ role = node.role
324
+ if node.title?
325
+ %(<formalpara#{_common_attributes id, role, reftext}>
336
326
  <title>#{node.title}</title>
337
327
  <para>#{content_spacer = node.content_model == :compound ? LF : ''}#{node.content}#{content_spacer}</para>
338
328
  </formalpara>)
339
- elsif id || role
340
- if node.content_model == :compound
341
- %(<para#{common_attributes id, role, reftext}>
329
+ elsif id || role
330
+ if node.content_model == :compound
331
+ %(<para#{_common_attributes id, role, reftext}>
342
332
  #{node.content}
343
333
  </para>)
344
- else
345
- %(<simpara#{common_attributes id, role, reftext}>#{node.content}</simpara>)
346
- end
347
334
  else
348
- resolve_content node
335
+ %(<simpara#{_common_attributes id, role, reftext}>#{node.content}</simpara>)
349
336
  end
337
+ else
338
+ _enclose_content node
350
339
  end
351
340
  end
341
+ end
352
342
 
353
- def page_break node
354
- '<simpara><?asciidoc-pagebreak?></simpara>'
355
- end
343
+ def page_break node
344
+ '<simpara><?asciidoc-pagebreak?></simpara>'
345
+ end
356
346
 
357
- def paragraph node
358
- if node.title?
359
- %(<formalpara#{common_attributes node.id, node.role, node.reftext}>
347
+ def paragraph node
348
+ if node.title?
349
+ %(<formalpara#{_common_attributes node.id, node.role, node.reftext}>
360
350
  <title>#{node.title}</title>
361
351
  <para>#{node.content}</para>
362
352
  </formalpara>)
363
- else
364
- %(<simpara#{common_attributes node.id, node.role, node.reftext}>#{node.content}</simpara>)
365
- end
353
+ else
354
+ %(<simpara#{_common_attributes node.id, node.role, node.reftext}>#{node.content}</simpara>)
366
355
  end
356
+ end
367
357
 
368
- def preamble node
369
- if node.document.doctype == 'book'
370
- %(<preface#{common_attributes node.id, node.role, node.reftext}>
371
- #{title_tag node, false}#{node.content}
358
+ def preamble node
359
+ if node.document.doctype == 'book'
360
+ %(<preface#{_common_attributes node.id, node.role, node.reftext}>
361
+ #{_title_tag node, false}#{node.content}
372
362
  </preface>)
373
- else
374
- node.content
375
- end
363
+ else
364
+ node.content
376
365
  end
366
+ end
377
367
 
378
- def quote node
379
- blockquote_tag(node, (node.has_role? 'epigraph') && 'epigraph') { resolve_content node }
380
- end
368
+ def quote node
369
+ _blockquote_tag(node, (node.has_role? 'epigraph') && 'epigraph') { _enclose_content node }
370
+ end
381
371
 
382
- def thematic_break node
383
- '<simpara><?asciidoc-hr?></simpara>'
384
- end
372
+ def thematic_break node
373
+ '<simpara><?asciidoc-hr?></simpara>'
374
+ end
385
375
 
386
- def sidebar node
387
- %(<sidebar#{common_attributes node.id, node.role, node.reftext}>
388
- #{title_tag node}#{resolve_content node}
376
+ def sidebar node
377
+ %(<sidebar#{_common_attributes node.id, node.role, node.reftext}>
378
+ #{_title_tag node}#{_enclose_content node}
389
379
  </sidebar>)
390
- end
391
-
392
- TABLE_PI_NAMES = ['dbhtml', 'dbfo', 'dblatex']
380
+ end
393
381
 
394
- def table node
395
- has_body = false
396
- result = []
397
- pgwide_attribute = (node.option? 'pgwide') ? ' pgwide="1"' : ''
398
- if (frame = node.attr 'frame', 'all') == 'ends'
399
- frame = 'topbot'
400
- end
401
- 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"' : ''}>)
402
- if (node.option? 'unbreakable')
403
- result << '<?dbfo keep-together="always"?>'
404
- elsif (node.option? 'breakable')
405
- result << '<?dbfo keep-together="auto"?>'
406
- end
407
- result << %(<title>#{node.title}</title>) if tag_name == 'table'
408
- col_width_key = if (width = (node.attr? 'width') ? (node.attr 'width') : nil)
409
- TABLE_PI_NAMES.each do |pi_name|
410
- result << %(<?#{pi_name} table-width="#{width}"?>)
411
- end
412
- 'colabswidth'
413
- else
414
- 'colpcwidth'
415
- end
416
- result << %(<tgroup cols="#{node.attr 'colcount'}">)
417
- node.columns.each do |col|
418
- result << %(<colspec colname="col_#{col.attr 'colnumber'}" colwidth="#{col.attr col_width_key}*"/>)
419
- end
420
- node.rows.by_section.each do |tsec, rows|
421
- next if rows.empty?
422
- has_body = true if tsec == :body
423
- result << %(<t#{tsec}>)
424
- rows.each do |row|
425
- result << '<row>'
426
- row.each do |cell|
427
- halign_attribute = (cell.attr? 'halign') ? %( align="#{cell.attr 'halign'}") : ''
428
- valign_attribute = (cell.attr? 'valign') ? %( valign="#{cell.attr 'valign'}") : ''
429
- colspan_attribute = cell.colspan ? %( namest="col_#{colnum = cell.column.attr 'colnumber'}" nameend="col_#{colnum + cell.colspan - 1}") : ''
430
- rowspan_attribute = cell.rowspan ? %( morerows="#{cell.rowspan - 1}") : ''
431
- # NOTE <entry> may not have whitespace (e.g., line breaks) as a direct descendant according to DocBook rules
432
- entry_start = %(<entry#{halign_attribute}#{valign_attribute}#{colspan_attribute}#{rowspan_attribute}>)
433
- if tsec == :head
434
- cell_content = cell.text
382
+ def table node
383
+ has_body = false
384
+ result = []
385
+ pgwide_attribute = (node.option? 'pgwide') ? ' pgwide="1"' : ''
386
+ if (frame = node.attr 'frame', 'all', 'table-frame') == 'ends'
387
+ frame = 'topbot'
388
+ end
389
+ grid = node.attr 'grid', nil, 'table-grid'
390
+ result << %(<#{tag_name = node.title? ? 'table' : 'informaltable'}#{_common_attributes node.id, node.role, node.reftext}#{pgwide_attribute} frame="#{frame}" rowsep="#{['none', 'cols'].include?(grid) ? 0 : 1}" colsep="#{['none', 'rows'].include?(grid) ? 0 : 1}"#{(node.attr? 'orientation', 'landscape', 'table-orientation') ? ' orient="land"' : ''}>)
391
+ if (node.option? 'unbreakable')
392
+ result << '<?dbfo keep-together="always"?>'
393
+ elsif (node.option? 'breakable')
394
+ result << '<?dbfo keep-together="auto"?>'
395
+ end
396
+ result << %(<title>#{node.title}</title>) if tag_name == 'table'
397
+ col_width_key = if (width = (node.attr? 'width') ? (node.attr 'width') : nil)
398
+ TABLE_PI_NAMES.each do |pi_name|
399
+ result << %(<?#{pi_name} table-width="#{width}"?>)
400
+ end
401
+ 'colabswidth'
402
+ else
403
+ 'colpcwidth'
404
+ end
405
+ result << %(<tgroup cols="#{node.attr 'colcount'}">)
406
+ node.columns.each do |col|
407
+ result << %(<colspec colname="col_#{col.attr 'colnumber'}" colwidth="#{col.attr col_width_key}*"/>)
408
+ end
409
+ node.rows.to_h.each do |tsec, rows|
410
+ next if rows.empty?
411
+ has_body = true if tsec == :body
412
+ result << %(<t#{tsec}>)
413
+ rows.each do |row|
414
+ result << '<row>'
415
+ row.each do |cell|
416
+ halign_attribute = (cell.attr? 'halign') ? %( align="#{cell.attr 'halign'}") : ''
417
+ valign_attribute = (cell.attr? 'valign') ? %( valign="#{cell.attr 'valign'}") : ''
418
+ colspan_attribute = cell.colspan ? %( namest="col_#{colnum = cell.column.attr 'colnumber'}" nameend="col_#{colnum + cell.colspan - 1}") : ''
419
+ rowspan_attribute = cell.rowspan ? %( morerows="#{cell.rowspan - 1}") : ''
420
+ # NOTE <entry> may not have whitespace (e.g., line breaks) as a direct descendant according to DocBook rules
421
+ entry_start = %(<entry#{halign_attribute}#{valign_attribute}#{colspan_attribute}#{rowspan_attribute}>)
422
+ if tsec == :head
423
+ cell_content = cell.text
424
+ else
425
+ case cell.style
426
+ when :asciidoc
427
+ cell_content = cell.content
428
+ when :literal
429
+ cell_content = %(<literallayout class="monospaced">#{cell.text}</literallayout>)
430
+ when :header
431
+ cell_content = (cell_content = cell.content).empty? ? '' : %(<simpara><emphasis role="strong">#{cell_content.join '</emphasis></simpara><simpara><emphasis role="strong">'}</emphasis></simpara>)
435
432
  else
436
- case cell.style
437
- when :asciidoc
438
- cell_content = cell.content
439
- when :verse
440
- cell_content = %(<literallayout>#{cell.text}</literallayout>)
441
- when :literal
442
- cell_content = %(<literallayout class="monospaced">#{cell.text}</literallayout>)
443
- when :header
444
- cell_content = (cell_content = cell.content).empty? ? '' : %(<simpara><emphasis role="strong">#{cell_content.join '</emphasis></simpara><simpara><emphasis role="strong">'}</emphasis></simpara>)
445
- else
446
- cell_content = (cell_content = cell.content).empty? ? '' : %(<simpara>#{cell_content.join '</simpara><simpara>'}</simpara>)
447
- end
433
+ cell_content = (cell_content = cell.content).empty? ? '' : %(<simpara>#{cell_content.join '</simpara><simpara>'}</simpara>)
448
434
  end
449
- entry_end = (node.document.attr? 'cellbgcolor') ? %(<?dbfo bgcolor="#{node.document.attr 'cellbgcolor'}"?></entry>) : '</entry>'
450
- result << %(#{entry_start}#{cell_content}#{entry_end})
451
435
  end
452
- result << '</row>'
436
+ entry_end = (node.document.attr? 'cellbgcolor') ? %(<?dbfo bgcolor="#{node.document.attr 'cellbgcolor'}"?></entry>) : '</entry>'
437
+ result << %(#{entry_start}#{cell_content}#{entry_end})
453
438
  end
454
- result << %(</t#{tsec}>)
439
+ result << '</row>'
455
440
  end
456
- result << '</tgroup>'
457
- result << %(</#{tag_name}>)
458
-
459
- logger.warn 'tables must have at least one body row' unless has_body
460
- result.join LF
441
+ result << %(</t#{tsec}>)
461
442
  end
443
+ result << '</tgroup>'
444
+ result << %(</#{tag_name}>)
462
445
 
463
- alias toc skip
446
+ logger.warn 'tables must have at least one body row' unless has_body
447
+ result.join LF
448
+ end
464
449
 
465
- def ulist node
466
- result = []
467
- if node.style == 'bibliography'
468
- result << %(<bibliodiv#{common_attributes node.id, node.role, node.reftext}>)
469
- result << %(<title>#{node.title}</title>) if node.title?
470
- node.items.each do |item|
471
- result << '<bibliomixed>'
472
- result << %(<bibliomisc>#{item.text}</bibliomisc>)
473
- result << item.content if item.blocks?
474
- result << '</bibliomixed>'
475
- end
476
- result << '</bibliodiv>'
477
- else
478
- mark_type = (checklist = node.option? 'checklist') ? 'none' : node.style
479
- mark_attribute = mark_type ? %( mark="#{mark_type}") : ''
480
- result << %(<itemizedlist#{common_attributes node.id, node.role, node.reftext}#{mark_attribute}>)
481
- result << %(<title>#{node.title}</title>) if node.title?
482
- node.items.each do |item|
483
- text_marker = if checklist && (item.attr? 'checkbox')
484
- (item.attr? 'checked') ? '&#10003; ' : '&#10063; '
485
- else
486
- ''
487
- end
488
- result << '<listitem>'
489
- result << %(<simpara>#{text_marker}#{item.text}</simpara>)
490
- result << item.content if item.blocks?
491
- result << '</listitem>'
492
- end
493
- result << '</itemizedlist>'
494
- end
450
+ alias toc _skip
495
451
 
496
- result.join LF
452
+ def ulist node
453
+ result = []
454
+ if node.style == 'bibliography'
455
+ result << %(<bibliodiv#{_common_attributes node.id, node.role, node.reftext}>)
456
+ result << %(<title>#{node.title}</title>) if node.title?
457
+ node.items.each do |item|
458
+ result << '<bibliomixed>'
459
+ result << %(<bibliomisc>#{item.text}</bibliomisc>)
460
+ result << item.content if item.blocks?
461
+ result << '</bibliomixed>'
462
+ end
463
+ result << '</bibliodiv>'
464
+ else
465
+ mark_type = (checklist = node.option? 'checklist') ? 'none' : node.style
466
+ mark_attribute = mark_type ? %( mark="#{mark_type}") : ''
467
+ result << %(<itemizedlist#{_common_attributes node.id, node.role, node.reftext}#{mark_attribute}>)
468
+ result << %(<title>#{node.title}</title>) if node.title?
469
+ node.items.each do |item|
470
+ text_marker = (item.attr? 'checked') ? '&#10003; ' : '&#10063; ' if checklist && (item.attr? 'checkbox')
471
+ result << %(<listitem#{_common_attributes item.id, item.role}>)
472
+ result << %(<simpara>#{text_marker || ''}#{item.text}</simpara>)
473
+ result << item.content if item.blocks?
474
+ result << '</listitem>'
475
+ end
476
+ result << '</itemizedlist>'
497
477
  end
478
+ result.join LF
479
+ end
498
480
 
499
- def verse node
500
- blockquote_tag(node, (node.has_role? 'epigraph') && 'epigraph') { %(<literallayout>#{node.content}</literallayout>) }
501
- end
481
+ def verse node
482
+ _blockquote_tag(node, (node.has_role? 'epigraph') && 'epigraph') { %(<literallayout>#{node.content}</literallayout>) }
483
+ end
502
484
 
503
- alias video skip
485
+ alias video _skip
504
486
 
505
- def inline_anchor node
506
- case node.type
507
- when :ref
508
- %(<anchor#{common_attributes((id = node.id), nil, node.reftext || %([#{id}]))}/>)
509
- when :xref
510
- if (path = node.attributes['path'])
511
- # QUESTION should we use refid as fallback text instead? (like the html5 backend?)
512
- %(<link xl:href="#{node.target}">#{node.text || path}</link>)
513
- else
514
- linkend = node.attributes['fragment'] || node.target
515
- (text = node.text) ? %(<link linkend="#{linkend}">#{text}</link>) : %(<xref linkend="#{linkend}"/>)
516
- end
517
- when :link
518
- %(<link xl:href="#{node.target}">#{node.text}</link>)
519
- when :bibref
520
- # NOTE technically node.text should be node.reftext, but subs have already been applied to text
521
- %(<anchor#{common_attributes node.id, nil, (text = node.text)}/>#{text})
487
+ def inline_anchor node
488
+ case node.type
489
+ when :ref
490
+ %(<anchor#{_common_attributes((id = node.id), nil, node.reftext || %([#{id}]))}/>)
491
+ when :xref
492
+ if (path = node.attributes['path'])
493
+ # QUESTION should we use refid as fallback text instead? (like the html5 backend?)
494
+ %(<link xl:href="#{node.target}">#{node.text || path}</link>)
522
495
  else
523
- logger.warn %(unknown anchor type: #{node.type.inspect})
524
- nil
525
- end
496
+ linkend = node.attributes['fragment'] || node.target
497
+ (text = node.text) ? %(<link linkend="#{linkend}">#{text}</link>) : %(<xref linkend="#{linkend}"/>)
498
+ end
499
+ when :link
500
+ %(<link xl:href="#{node.target}">#{node.text}</link>)
501
+ when :bibref
502
+ %(<anchor#{_common_attributes node.id, nil, "[#{node.reftext || node.id}]"}/>#{text})
503
+ else
504
+ logger.warn %(unknown anchor type: #{node.type.inspect})
505
+ nil
526
506
  end
507
+ end
527
508
 
528
- def inline_break node
529
- %(#{node.text}<?asciidoc-br?>)
530
- end
509
+ def inline_break node
510
+ %(#{node.text}<?asciidoc-br?>)
511
+ end
531
512
 
532
- def inline_button node
533
- %(<guibutton>#{node.text}</guibutton>)
534
- end
513
+ def inline_button node
514
+ %(<guibutton>#{node.text}</guibutton>)
515
+ end
535
516
 
536
- def inline_callout node
537
- %(<co#{common_attributes node.id}/>)
538
- end
517
+ def inline_callout node
518
+ %(<co#{_common_attributes node.id}/>)
519
+ end
539
520
 
540
- def inline_footnote node
541
- if node.type == :xref
542
- %(<footnoteref linkend="#{node.target}"/>)
543
- else
544
- %(<footnote#{common_attributes node.id}><simpara>#{node.text}</simpara></footnote>)
545
- end
521
+ def inline_footnote node
522
+ if node.type == :xref
523
+ %(<footnoteref linkend="#{node.target}"/>)
524
+ else
525
+ %(<footnote#{_common_attributes node.id}><simpara>#{node.text}</simpara></footnote>)
546
526
  end
527
+ end
547
528
 
548
- def inline_image node
549
- width_attribute = (node.attr? 'width') ? %( contentwidth="#{node.attr 'width'}") : ''
550
- depth_attribute = (node.attr? 'height') ? %( contentdepth="#{node.attr 'height'}") : ''
551
- %(<inlinemediaobject>
529
+ def inline_image node
530
+ width_attribute = (node.attr? 'width') ? %( contentwidth="#{node.attr 'width'}") : ''
531
+ depth_attribute = (node.attr? 'height') ? %( contentdepth="#{node.attr 'height'}") : ''
532
+ %(<inlinemediaobject>
552
533
  <imageobject>
553
534
  <imagedata fileref="#{node.type == 'icon' ? (node.icon_uri node.target) : (node.image_uri node.target)}"#{width_attribute}#{depth_attribute}/>
554
535
  </imageobject>
555
536
  <textobject><phrase>#{node.alt}</phrase></textobject>
556
537
  </inlinemediaobject>)
557
- end
538
+ end
558
539
 
559
- def inline_indexterm node
560
- if node.type == :visible
561
- %(<indexterm><primary>#{node.text}</primary></indexterm>#{node.text})
562
- else
563
- terms = node.attr 'terms'
564
- result = []
565
- if (numterms = terms.size) > 2
566
- result << %(<indexterm>
540
+ def inline_indexterm node
541
+ if node.type == :visible
542
+ %(<indexterm><primary>#{node.text}</primary></indexterm>#{node.text})
543
+ else
544
+ terms = node.attr 'terms'
545
+ result = []
546
+ if (numterms = terms.size) > 2
547
+ result << %(<indexterm>
567
548
  <primary>#{terms[0]}</primary><secondary>#{terms[1]}</secondary><tertiary>#{terms[2]}</tertiary>
568
549
  </indexterm>)
569
- end
570
- if numterms > 1
571
- result << %(<indexterm>
550
+ end
551
+ if numterms > 1
552
+ result << %(<indexterm>
572
553
  <primary>#{terms[-2]}</primary><secondary>#{terms[-1]}</secondary>
573
554
  </indexterm>)
574
- end
575
- result << %(<indexterm>
555
+ end
556
+ result << %(<indexterm>
576
557
  <primary>#{terms[-1]}</primary>
577
558
  </indexterm>)
578
- result.join LF
579
- end
559
+ result.join LF
580
560
  end
561
+ end
581
562
 
582
- def inline_kbd node
583
- if (keys = node.attr 'keys').size == 1
584
- %(<keycap>#{keys[0]}</keycap>)
585
- else
586
- %(<keycombo><keycap>#{keys.join '</keycap><keycap>'}</keycap></keycombo>)
587
- end
563
+ def inline_kbd node
564
+ if (keys = node.attr 'keys').size == 1
565
+ %(<keycap>#{keys[0]}</keycap>)
566
+ else
567
+ %(<keycombo><keycap>#{keys.join '</keycap><keycap>'}</keycap></keycombo>)
588
568
  end
569
+ end
589
570
 
590
- def inline_menu node
591
- menu = node.attr 'menu'
592
- if (submenus = node.attr 'submenus').empty?
593
- if (menuitem = node.attr 'menuitem', nil, false)
594
- %(<menuchoice><guimenu>#{menu}</guimenu> <guimenuitem>#{menuitem}</guimenuitem></menuchoice>)
595
- else
596
- %(<guimenu>#{menu}</guimenu>)
597
- end
571
+ def inline_menu node
572
+ menu = node.attr 'menu'
573
+ if (submenus = node.attr 'submenus').empty?
574
+ if (menuitem = node.attr 'menuitem')
575
+ %(<menuchoice><guimenu>#{menu}</guimenu> <guimenuitem>#{menuitem}</guimenuitem></menuchoice>)
598
576
  else
599
- %(<menuchoice><guimenu>#{menu}</guimenu> <guisubmenu>#{submenus.join '</guisubmenu> <guisubmenu>'}</guisubmenu> <guimenuitem>#{node.attr 'menuitem'}</guimenuitem></menuchoice>)
577
+ %(<guimenu>#{menu}</guimenu>)
600
578
  end
579
+ else
580
+ %(<menuchoice><guimenu>#{menu}</guimenu> <guisubmenu>#{submenus.join '</guisubmenu> <guisubmenu>'}</guisubmenu> <guimenuitem>#{node.attr 'menuitem'}</guimenuitem></menuchoice>)
601
581
  end
582
+ end
602
583
 
603
- (QUOTE_TAGS = {
604
- :monospaced => ['<literal>', '</literal>', false],
605
- :emphasis => ['<emphasis>', '</emphasis>', true],
606
- :strong => ['<emphasis role="strong">', '</emphasis>', true],
607
- :double => ['<quote>', '</quote>', true],
608
- :single => ['<quote>', '</quote>', true],
609
- :mark => ['<emphasis role="marked">', '</emphasis>', false],
610
- :superscript => ['<superscript>', '</superscript>', false],
611
- :subscript => ['<subscript>', '</subscript>', false]
612
- }).default = ['', '', true]
613
-
614
- def inline_quoted node
615
- if (type = node.type) == :asciimath
616
- if (@asciimath ||= ((defined? ::AsciiMath) || (Helpers.require_library 'asciimath', true, :warn)).nil? ? :unavailable : :loaded) == :loaded
617
- # NOTE fop requires jeuclid to process raw mathml
618
- %(<inlineequation>#{(::AsciiMath.parse node.text).to_mathml 'mml:', 'xmlns:mml' => 'http://www.w3.org/1998/Math/MathML'}</inlineequation>)
584
+ def inline_quoted node
585
+ if (type = node.type) == :asciimath
586
+ # NOTE fop requires jeuclid to process mathml markup
587
+ _asciimath_available? ? %(<inlineequation>#{(::AsciiMath.parse node.text).to_mathml 'mml:', 'xmlns:mml' => 'http://www.w3.org/1998/Math/MathML'}</inlineequation>) : %(<inlineequation><mathphrase><![CDATA[#{node.text}]]></mathphrase></inlineequation>)
588
+ elsif type == :latexmath
589
+ # unhandled math; pass source to alt and required mathphrase element; dblatex will process alt as LaTeX math
590
+ %(<inlineequation><alt><![CDATA[#{equation = node.text}]]></alt><mathphrase><![CDATA[#{equation}]]></mathphrase></inlineequation>)
591
+ else
592
+ open, close, supports_phrase = QUOTE_TAGS[type]
593
+ text = node.text
594
+ if node.role
595
+ if supports_phrase
596
+ quoted_text = %(#{open}<phrase role="#{node.role}">#{text}</phrase>#{close})
619
597
  else
620
- %(<inlineequation><mathphrase><![CDATA[#{node.text}]]></mathphrase></inlineequation>)
598
+ quoted_text = %(#{open.chop} role="#{node.role}">#{text}#{close})
621
599
  end
622
- elsif type == :latexmath
623
- # unhandled math; pass source to alt and required mathphrase element; dblatex will process alt as LaTeX math
624
- %(<inlineequation><alt><![CDATA[#{equation = node.text}]]></alt><mathphrase><![CDATA[#{equation}]]></mathphrase></inlineequation>)
625
600
  else
626
- open, close, supports_phrase = QUOTE_TAGS[type]
627
- text = node.text
628
- if node.role
629
- if supports_phrase
630
- quoted_text = %(#{open}<phrase role="#{node.role}">#{text}</phrase>#{close})
631
- else
632
- quoted_text = %(#{open.chop} role="#{node.role}">#{text}#{close})
633
- end
634
- else
635
- quoted_text = %(#{open}#{text}#{close})
636
- end
637
-
638
- node.id ? %(<anchor#{common_attributes node.id, nil, text}/>#{quoted_text}) : quoted_text
601
+ quoted_text = %(#{open}#{text}#{close})
639
602
  end
603
+
604
+ node.id ? %(<anchor#{_common_attributes node.id, nil, text}/>#{quoted_text}) : quoted_text
640
605
  end
606
+ end
641
607
 
642
- def common_attributes id, role = nil, reftext = nil
643
- attrs = id ? %( xml:id="#{id}") : ''
644
- attrs = %(#{attrs} role="#{role}") if role
645
- if reftext
646
- if (reftext.include? '<') && ((reftext = reftext.gsub XmlSanitizeRx, '').include? ' ')
647
- reftext = (reftext.squeeze ' ').strip
648
- end
649
- reftext = (reftext.gsub '"', '&quot;') if reftext.include? '"'
650
- attrs = %(#{attrs} xreflabel="#{reftext}")
608
+ private
609
+
610
+ def _common_attributes id, role = nil, reftext = nil
611
+ if id
612
+ attrs = %( xml:id="#{id}"#{role ? %[ role="#{role}"] : ''})
613
+ elsif role
614
+ attrs = %( role="#{role}")
615
+ else
616
+ attrs = ''
617
+ end
618
+ if reftext
619
+ if (reftext.include? '<') && ((reftext = reftext.gsub XmlSanitizeRx, '').include? ' ')
620
+ reftext = (reftext.squeeze ' ').strip
651
621
  end
622
+ reftext = (reftext.gsub '"', '&quot;') if reftext.include? '"'
623
+ %(#{attrs} xreflabel="#{reftext}")
624
+ else
652
625
  attrs
653
626
  end
627
+ end
654
628
 
655
- def doctype_declaration root_tag_name
656
- nil
657
- end
658
-
659
- def author_tag author
660
- result = []
661
- result << '<author>'
662
- result << '<personname>'
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
666
- result << '</personname>'
667
- result << %(<email>#{author.email}</email>) if author.email
668
- result << '</author>'
669
- result.join LF
670
- end
629
+ def _author_tag author
630
+ result = []
631
+ result << '<author>'
632
+ result << '<personname>'
633
+ result << %(<firstname>#{author.firstname}</firstname>) if author.firstname
634
+ result << %(<othername>#{author.middlename}</othername>) if author.middlename
635
+ result << %(<surname>#{author.lastname}</surname>) if author.lastname
636
+ result << '</personname>'
637
+ result << %(<email>#{author.email}</email>) if author.email
638
+ result << '</author>'
639
+ result.join LF
640
+ end
671
641
 
672
- def document_info_tag doc, info_tag_prefix, use_info_tag_prefix = false
673
- info_tag_prefix = '' unless use_info_tag_prefix
674
- result = []
675
- result << %(<#{info_tag_prefix}info>)
676
- result << document_title_tags(doc.doctitle :partition => true, :use_fallback => true) unless doc.notitle
677
- if (date = (doc.attr? 'revdate') ? (doc.attr 'revdate') : ((doc.attr? 'reproducible') ? nil : (doc.attr 'docdate')))
678
- result << %(<date>#{date}</date>)
679
- end
680
- if doc.attr? 'copyright'
681
- CopyrightRx =~ (doc.attr 'copyright')
682
- result << '<copyright>'
683
- result << %(<holder>#{$1}</holder>)
684
- result << %(<year>#{$2}</year>) if $2
685
- result << '</copyright>'
642
+ def _document_info_tag doc
643
+ result = ['<info>']
644
+ unless doc.notitle
645
+ if (title = doc.doctitle partition: true, use_fallback: true).subtitle?
646
+ result << %(<title>#{title.main}</title>
647
+ <subtitle>#{title.subtitle}</subtitle>)
648
+ else
649
+ result << %(<title>#{title}</title>)
686
650
  end
687
- if doc.has_header?
688
- unless (authors = doc.authors).empty?
689
- if authors.size > 1
690
- result << '<authorgroup>'
691
- authors.each {|author| result << (author_tag author) }
692
- result << '</authorgroup>'
693
- else
694
- result << author_tag(author = authors[0])
695
- result << %(<authorinitials>#{author.initials}</authorinitials>) if author.initials
696
- end
651
+ end
652
+ if (date = (doc.attr? 'revdate') ? (doc.attr 'revdate') : ((doc.attr? 'reproducible') ? nil : (doc.attr 'docdate')))
653
+ result << %(<date>#{date}</date>)
654
+ end
655
+ if doc.attr? 'copyright'
656
+ CopyrightRx =~ (doc.attr 'copyright')
657
+ result << '<copyright>'
658
+ result << %(<holder>#{$1}</holder>)
659
+ result << %(<year>#{$2}</year>) if $2
660
+ result << '</copyright>'
661
+ end
662
+ if doc.header?
663
+ unless (authors = doc.authors).empty?
664
+ if authors.size > 1
665
+ result << '<authorgroup>'
666
+ authors.each {|author| result << (_author_tag author) }
667
+ result << '</authorgroup>'
668
+ else
669
+ result << _author_tag(author = authors[0])
670
+ result << %(<authorinitials>#{author.initials}</authorinitials>) if author.initials
697
671
  end
698
- if (doc.attr? 'revdate') && ((doc.attr? 'revnumber') || (doc.attr? 'revremark'))
699
- result << %(<revhistory>
672
+ end
673
+ if (doc.attr? 'revdate') && ((doc.attr? 'revnumber') || (doc.attr? 'revremark'))
674
+ result << %(<revhistory>
700
675
  <revision>)
701
- result << %(<revnumber>#{doc.attr 'revnumber'}</revnumber>) if doc.attr? 'revnumber'
702
- result << %(<date>#{doc.attr 'revdate'}</date>) if doc.attr? 'revdate'
703
- result << %(<authorinitials>#{doc.attr 'authorinitials'}</authorinitials>) if doc.attr? 'authorinitials'
704
- result << %(<revremark>#{doc.attr 'revremark'}</revremark>) if doc.attr? 'revremark'
705
- result << %(</revision>
676
+ result << %(<revnumber>#{doc.attr 'revnumber'}</revnumber>) if doc.attr? 'revnumber'
677
+ result << %(<date>#{doc.attr 'revdate'}</date>) if doc.attr? 'revdate'
678
+ result << %(<authorinitials>#{doc.attr 'authorinitials'}</authorinitials>) if doc.attr? 'authorinitials'
679
+ result << %(<revremark>#{doc.attr 'revremark'}</revremark>) if doc.attr? 'revremark'
680
+ result << %(</revision>
706
681
  </revhistory>)
682
+ end
683
+ if (doc.attr? 'front-cover-image') || (doc.attr? 'back-cover-image')
684
+ if (back_cover_tag = _cover_tag doc, 'back')
685
+ result << (_cover_tag doc, 'front', true)
686
+ result << back_cover_tag
687
+ elsif (front_cover_tag = _cover_tag doc, 'front')
688
+ result << front_cover_tag
707
689
  end
708
- unless use_info_tag_prefix
709
- if (doc.attr? 'front-cover-image') || (doc.attr? 'back-cover-image')
710
- if (back_cover_tag = cover_tag doc, 'back')
711
- result << (cover_tag doc, 'front', true)
712
- result << back_cover_tag
713
- elsif (front_cover_tag = cover_tag doc, 'front')
714
- result << front_cover_tag
715
- end
716
- end
717
- end
718
- unless (head_docinfo = doc.docinfo).empty?
719
- result << head_docinfo
720
- end
721
- result << %(<orgname>#{doc.attr 'orgname'}</orgname>) if doc.attr? 'orgname'
722
690
  end
723
- result << %(</#{info_tag_prefix}info>)
724
-
725
- if doc.doctype == 'manpage'
726
- result << '<refmeta>'
727
- result << %(<refentrytitle>#{doc.attr 'mantitle'}</refentrytitle>) if doc.attr? 'mantitle'
728
- result << %(<manvolnum>#{doc.attr 'manvolnum'}</manvolnum>) if doc.attr? 'manvolnum'
729
- result << %(<refmiscinfo class="source">#{doc.attr 'mansource', '&#160;'}</refmiscinfo>)
730
- result << %(<refmiscinfo class="manual">#{doc.attr 'manmanual', '&#160;'}</refmiscinfo>)
731
- result << '</refmeta>'
732
- result << '<refnamediv>'
733
- result += (doc.attr 'mannames').map {|n| %(<refname>#{n}</refname>) } if doc.attr? 'mannames'
734
- result << %(<refpurpose>#{doc.attr 'manpurpose'}</refpurpose>) if doc.attr? 'manpurpose'
735
- result << '</refnamediv>'
691
+ result << %(<orgname>#{doc.attr 'orgname'}</orgname>) if doc.attr? 'orgname'
692
+ unless (docinfo_content = doc.docinfo).empty?
693
+ result << docinfo_content
736
694
  end
737
-
738
- result.join LF
739
695
  end
696
+ result << '</info>'
740
697
 
741
- def document_ns_attributes doc
742
- ' xmlns="http://docbook.org/ns/docbook" xmlns:xl="http://www.w3.org/1999/xlink" version="5.0"'
698
+ if doc.doctype == 'manpage'
699
+ result << '<refmeta>'
700
+ result << %(<refentrytitle>#{doc.attr 'mantitle'}</refentrytitle>) if doc.attr? 'mantitle'
701
+ result << %(<manvolnum>#{doc.attr 'manvolnum'}</manvolnum>) if doc.attr? 'manvolnum'
702
+ result << %(<refmiscinfo class="source">#{doc.attr 'mansource', '&#160;'}</refmiscinfo>)
703
+ result << %(<refmiscinfo class="manual">#{doc.attr 'manmanual', '&#160;'}</refmiscinfo>)
704
+ result << '</refmeta>'
705
+ result << '<refnamediv>'
706
+ result += (doc.attr 'mannames').map {|n| %(<refname>#{n}</refname>) } if doc.attr? 'mannames'
707
+ result << %(<refpurpose>#{doc.attr 'manpurpose'}</refpurpose>) if doc.attr? 'manpurpose'
708
+ result << '</refnamediv>'
743
709
  end
744
710
 
745
- def lang_attribute_name
746
- 'xml:lang'
747
- end
748
-
749
- def document_title_tags title
750
- if title.subtitle?
751
- %(<title>#{title.main}</title>
752
- <subtitle>#{title.subtitle}</subtitle>)
753
- else
754
- %(<title>#{title}</title>)
755
- end
756
- end
711
+ result.join LF
712
+ end
757
713
 
758
- # FIXME this should be handled through a template mechanism
759
- def resolve_content node
760
- node.content_model == :compound ? node.content : %(<simpara>#{node.content}</simpara>)
761
- end
714
+ # FIXME this should be handled through a template mechanism
715
+ def _enclose_content node
716
+ node.content_model == :compound ? node.content : %(<simpara>#{node.content}</simpara>)
717
+ end
762
718
 
763
- def title_tag node, optional = true
764
- !optional || node.title? ? %(<title>#{node.title}</title>\n) : ''
765
- end
719
+ def _title_tag node, optional = true
720
+ !optional || node.title? ? %(<title>#{node.title}</title>\n) : ''
721
+ end
766
722
 
767
- def cover_tag doc, face, use_placeholder = false
768
- if (cover_image = doc.attr %(#{face}-cover-image))
769
- width_attr = ''
770
- depth_attr = ''
771
- if (cover_image.include? ':') && ImageMacroRx =~ cover_image
772
- cover_image = doc.image_uri $1
773
- unless $2.empty?
774
- attrs = (AttributeList.new $2).parse ['alt', 'width', 'height']
775
- if attrs.key? 'scaledwidth'
776
- # NOTE scalefit="1" is the default in this case
777
- width_attr = %( width="#{attrs['scaledwidth']}")
778
- else
779
- width_attr = %( contentwidth="#{attrs['width']}") if attrs.key? 'width'
780
- depth_attr = %( contentdepth="#{attrs['height']}") if attrs.key? 'height'
781
- end
723
+ def _cover_tag doc, face, use_placeholder = false
724
+ if (cover_image = doc.attr %(#{face}-cover-image))
725
+ width_attr = ''
726
+ depth_attr = ''
727
+ if (cover_image.include? ':') && ImageMacroRx =~ cover_image
728
+ cover_image = doc.image_uri $1
729
+ unless $2.empty?
730
+ attrs = (AttributeList.new $2).parse ['alt', 'width', 'height']
731
+ if attrs.key? 'scaledwidth'
732
+ # NOTE scalefit="1" is the default in this case
733
+ width_attr = %( width="#{attrs['scaledwidth']}")
734
+ else
735
+ width_attr = %( contentwidth="#{attrs['width']}") if attrs.key? 'width'
736
+ depth_attr = %( contentdepth="#{attrs['height']}") if attrs.key? 'height'
782
737
  end
783
738
  end
784
- %(<cover role="#{face}">
739
+ end
740
+ %(<cover role="#{face}">
785
741
  <mediaobject>
786
742
  <imageobject>
787
743
  <imagedata fileref="#{cover_image}"#{width_attr}#{depth_attr}/>
788
744
  </imageobject>
789
745
  </mediaobject>
790
746
  </cover>)
791
- elsif use_placeholder
792
- %(<cover role="#{face}"/>)
793
- end
747
+ elsif use_placeholder
748
+ %(<cover role="#{face}"/>)
794
749
  end
750
+ end
795
751
 
796
- def blockquote_tag node, tag_name = nil
797
- if tag_name
798
- start_tag, end_tag = %(<#{tag_name}), %(</#{tag_name}>)
799
- else
800
- start_tag, end_tag = '<blockquote', '</blockquote>'
801
- end
802
- result = [%(#{start_tag}#{common_attributes node.id, node.role, node.reftext}>)]
803
- result << %(<title>#{node.title}</title>) if node.title?
804
- if (node.attr? 'attribution') || (node.attr? 'citetitle')
805
- result << '<attribution>'
806
- result << (node.attr 'attribution') if node.attr? 'attribution'
807
- result << %(<citetitle>#{node.attr 'citetitle'}</citetitle>) if node.attr? 'citetitle'
808
- result << '</attribution>'
809
- end
810
- result << yield
811
- result << end_tag
812
- result.join LF
813
- end
752
+ def _blockquote_tag node, tag_name = nil
753
+ if tag_name
754
+ start_tag, end_tag = %(<#{tag_name}), %(</#{tag_name}>)
755
+ else
756
+ start_tag, end_tag = '<blockquote', '</blockquote>'
757
+ end
758
+ result = [%(#{start_tag}#{_common_attributes node.id, node.role, node.reftext}>)]
759
+ result << %(<title>#{node.title}</title>) if node.title?
760
+ if (node.attr? 'attribution') || (node.attr? 'citetitle')
761
+ result << '<attribution>'
762
+ result << (node.attr 'attribution') if node.attr? 'attribution'
763
+ result << %(<citetitle>#{node.attr 'citetitle'}</citetitle>) if node.attr? 'citetitle'
764
+ result << '</attribution>'
765
+ end
766
+ result << yield
767
+ result << end_tag
768
+ result.join LF
769
+ end
770
+
771
+ def _asciimath_available?
772
+ (@asciimath_status ||= _load_asciimath) == :loaded
773
+ end
774
+
775
+ def _load_asciimath
776
+ (defined? ::AsciiMath.parse) ? :loaded : (Helpers.require_library 'asciimath', true, :warn).nil? ? :unavailable : :loaded
814
777
  end
815
778
  end
779
+ end