asciidoctor 1.5.8 → 2.0.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (197) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +11 -0
  3. data/CHANGELOG.adoc +628 -45
  4. data/LICENSE +2 -1
  5. data/README-de.adoc +28 -38
  6. data/README-fr.adoc +30 -43
  7. data/README-jp.adoc +255 -201
  8. data/README-zh_CN.adoc +40 -44
  9. data/README.adoc +170 -143
  10. data/asciidoctor.gemspec +22 -34
  11. data/bin/asciidoctor +5 -4
  12. data/data/locale/attributes-ar.adoc +4 -3
  13. data/data/locale/attributes-be.adoc +23 -0
  14. data/data/locale/attributes-bg.adoc +4 -3
  15. data/data/locale/attributes-ca.adoc +6 -5
  16. data/data/locale/attributes-cs.adoc +4 -3
  17. data/data/locale/attributes-da.adoc +6 -5
  18. data/data/locale/attributes-de.adoc +6 -5
  19. data/data/locale/attributes-en.adoc +4 -4
  20. data/data/locale/attributes-es.adoc +6 -5
  21. data/data/locale/attributes-fa.adoc +4 -3
  22. data/data/locale/attributes-fi.adoc +4 -3
  23. data/data/locale/attributes-fr.adoc +8 -7
  24. data/data/locale/attributes-hu.adoc +4 -3
  25. data/data/locale/attributes-id.adoc +4 -3
  26. data/data/locale/attributes-it.adoc +6 -5
  27. data/data/locale/attributes-ja.adoc +4 -3
  28. data/data/locale/{attributes-kr.adoc → attributes-ko.adoc} +4 -3
  29. data/data/locale/attributes-nb.adoc +4 -3
  30. data/data/locale/attributes-nl.adoc +6 -5
  31. data/data/locale/attributes-nn.adoc +4 -3
  32. data/data/locale/attributes-pl.adoc +8 -7
  33. data/data/locale/attributes-pt.adoc +6 -5
  34. data/data/locale/attributes-pt_BR.adoc +6 -5
  35. data/data/locale/attributes-ro.adoc +4 -3
  36. data/data/locale/attributes-ru.adoc +6 -5
  37. data/data/locale/attributes-sr.adoc +4 -4
  38. data/data/locale/attributes-sr_Latn.adoc +4 -4
  39. data/data/locale/attributes-sv.adoc +4 -4
  40. data/data/locale/attributes-th.adoc +23 -0
  41. data/data/locale/attributes-tr.adoc +4 -3
  42. data/data/locale/attributes-uk.adoc +6 -5
  43. data/data/locale/attributes-vi.adoc +23 -0
  44. data/data/locale/attributes-zh_CN.adoc +4 -3
  45. data/data/locale/attributes-zh_TW.adoc +4 -3
  46. data/data/reference/syntax.adoc +296 -0
  47. data/data/stylesheets/asciidoctor-default.css +120 -114
  48. data/data/stylesheets/coderay-asciidoctor.css +15 -17
  49. data/lib/asciidoctor/abstract_block.rb +146 -140
  50. data/lib/asciidoctor/abstract_node.rb +152 -170
  51. data/lib/asciidoctor/attribute_list.rb +77 -89
  52. data/lib/asciidoctor/block.rb +29 -28
  53. data/lib/asciidoctor/callouts.rb +4 -2
  54. data/lib/asciidoctor/cli/invoker.rb +20 -24
  55. data/lib/asciidoctor/cli/options.rb +107 -96
  56. data/lib/asciidoctor/cli.rb +3 -2
  57. data/lib/asciidoctor/convert.rb +199 -0
  58. data/lib/asciidoctor/converter/composite.rb +40 -48
  59. data/lib/asciidoctor/converter/docbook5.rb +627 -644
  60. data/lib/asciidoctor/converter/html5.rb +1053 -951
  61. data/lib/asciidoctor/converter/manpage.rb +581 -532
  62. data/lib/asciidoctor/converter/template.rb +232 -271
  63. data/lib/asciidoctor/converter.rb +370 -185
  64. data/lib/asciidoctor/core_ext/float/truncate.rb +20 -0
  65. data/lib/asciidoctor/core_ext/hash/merge.rb +8 -0
  66. data/lib/asciidoctor/core_ext/match_data/names.rb +7 -0
  67. data/lib/asciidoctor/core_ext/nil_or_empty.rb +1 -0
  68. data/lib/asciidoctor/core_ext/regexp/is_match.rb +4 -2
  69. data/lib/asciidoctor/core_ext.rb +8 -17
  70. data/lib/asciidoctor/document.rb +503 -461
  71. data/lib/asciidoctor/extensions.rb +127 -174
  72. data/lib/asciidoctor/helpers.rb +184 -107
  73. data/lib/asciidoctor/inline.rb +9 -12
  74. data/lib/asciidoctor/list.rb +11 -29
  75. data/lib/asciidoctor/load.rb +119 -0
  76. data/lib/asciidoctor/logging.rb +22 -17
  77. data/lib/asciidoctor/parser.rb +673 -719
  78. data/lib/asciidoctor/path_resolver.rb +48 -33
  79. data/lib/asciidoctor/reader.rb +383 -338
  80. data/lib/asciidoctor/rouge_ext.rb +39 -0
  81. data/lib/asciidoctor/rx.rb +723 -0
  82. data/lib/asciidoctor/section.rb +17 -16
  83. data/lib/asciidoctor/stylesheets.rb +19 -37
  84. data/lib/asciidoctor/substitutors.rb +926 -1022
  85. data/lib/asciidoctor/syntax_highlighter/coderay.rb +88 -0
  86. data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +34 -0
  87. data/lib/asciidoctor/syntax_highlighter/html_pipeline.rb +10 -0
  88. data/lib/asciidoctor/syntax_highlighter/prettify.rb +30 -0
  89. data/lib/asciidoctor/syntax_highlighter/pygments.rb +157 -0
  90. data/lib/asciidoctor/syntax_highlighter/rouge.rb +143 -0
  91. data/lib/asciidoctor/syntax_highlighter.rb +253 -0
  92. data/lib/asciidoctor/table.rb +152 -114
  93. data/lib/asciidoctor/timings.rb +7 -5
  94. data/lib/asciidoctor/version.rb +2 -1
  95. data/lib/asciidoctor/writer.rb +30 -0
  96. data/lib/asciidoctor.rb +266 -1340
  97. data/man/asciidoctor.1 +49 -47
  98. data/man/asciidoctor.adoc +54 -45
  99. metadata +50 -245
  100. data/CONTRIBUTING.adoc +0 -185
  101. data/Gemfile +0 -60
  102. data/Rakefile +0 -129
  103. data/bin/asciidoctor-safe +0 -15
  104. data/features/open_block.feature +0 -92
  105. data/features/pass_block.feature +0 -66
  106. data/features/step_definitions.rb +0 -49
  107. data/features/text_formatting.feature +0 -57
  108. data/features/xref.feature +0 -1039
  109. data/lib/asciidoctor/converter/base.rb +0 -59
  110. data/lib/asciidoctor/converter/docbook45.rb +0 -93
  111. data/lib/asciidoctor/converter/factory.rb +0 -226
  112. data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +0 -6
  113. data/lib/asciidoctor/core_ext/1.8.7/concurrent/hash.rb +0 -5
  114. data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +0 -4
  115. data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +0 -6
  116. data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +0 -5
  117. data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +0 -6
  118. data/lib/asciidoctor/core_ext/1.8.7/string/limit_bytesize.rb +0 -29
  119. data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +0 -6
  120. data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +0 -6
  121. data/lib/asciidoctor/core_ext/string/limit_bytesize.rb +0 -10
  122. data/test/api_test.rb +0 -1240
  123. data/test/attribute_list_test.rb +0 -242
  124. data/test/attributes_test.rb +0 -1623
  125. data/test/blocks_test.rb +0 -3870
  126. data/test/converter_test.rb +0 -470
  127. data/test/document_test.rb +0 -1853
  128. data/test/extensions_test.rb +0 -1560
  129. data/test/fixtures/asciidoc_index.txt +0 -521
  130. data/test/fixtures/basic-docinfo-footer.html +0 -6
  131. data/test/fixtures/basic-docinfo-footer.xml +0 -8
  132. data/test/fixtures/basic-docinfo.html +0 -1
  133. data/test/fixtures/basic-docinfo.xml +0 -4
  134. data/test/fixtures/basic.asciidoc +0 -5
  135. data/test/fixtures/chapter-a.adoc +0 -3
  136. data/test/fixtures/child-include.adoc +0 -5
  137. data/test/fixtures/circle.svg +0 -9
  138. data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +0 -6
  139. data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +0 -6
  140. data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +0 -3
  141. data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +0 -5
  142. data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +0 -1
  143. data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +0 -6
  144. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +0 -3
  145. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +0 -5
  146. data/test/fixtures/custom-docinfodir/basic-docinfo.html +0 -1
  147. data/test/fixtures/custom-docinfodir/docinfo.html +0 -1
  148. data/test/fixtures/docinfo-footer.html +0 -1
  149. data/test/fixtures/docinfo-footer.xml +0 -9
  150. data/test/fixtures/docinfo.html +0 -1
  151. data/test/fixtures/docinfo.xml +0 -3
  152. data/test/fixtures/doctime-localtime.adoc +0 -2
  153. data/test/fixtures/dot.gif +0 -0
  154. data/test/fixtures/encoding.asciidoc +0 -13
  155. data/test/fixtures/file-with-missing-include.adoc +0 -1
  156. data/test/fixtures/grandchild-include.adoc +0 -3
  157. data/test/fixtures/hello-asciidoctor.pdf +0 -69
  158. data/test/fixtures/include-file.asciidoc +0 -24
  159. data/test/fixtures/include-file.jsx +0 -8
  160. data/test/fixtures/include-file.ml +0 -3
  161. data/test/fixtures/include-file.xml +0 -5
  162. data/test/fixtures/lists.adoc +0 -96
  163. data/test/fixtures/master.adoc +0 -5
  164. data/test/fixtures/mismatched-end-tag.adoc +0 -7
  165. data/test/fixtures/other-chapters.adoc +0 -11
  166. data/test/fixtures/outer-include.adoc +0 -5
  167. data/test/fixtures/parent-include-restricted.adoc +0 -5
  168. data/test/fixtures/parent-include.adoc +0 -5
  169. data/test/fixtures/sample.asciidoc +0 -30
  170. data/test/fixtures/section-a.adoc +0 -4
  171. data/test/fixtures/stylesheets/custom.css +0 -3
  172. data/test/fixtures/subdir/index.adoc +0 -3
  173. data/test/fixtures/subdir/inner-include.adoc +0 -3
  174. data/test/fixtures/subdir/middle-include.adoc +0 -5
  175. data/test/fixtures/subs-docinfo.html +0 -2
  176. data/test/fixtures/subs.adoc +0 -6
  177. data/test/fixtures/tagged-class-enclosed.rb +0 -25
  178. data/test/fixtures/tagged-class.rb +0 -23
  179. data/test/fixtures/tip.gif +0 -0
  180. data/test/fixtures/unclosed-tag.adoc +0 -3
  181. data/test/fixtures/unexpected-end-tag.adoc +0 -4
  182. data/test/invoker_test.rb +0 -745
  183. data/test/links_test.rb +0 -855
  184. data/test/lists_test.rb +0 -5151
  185. data/test/logger_test.rb +0 -211
  186. data/test/manpage_test.rb +0 -660
  187. data/test/options_test.rb +0 -262
  188. data/test/paragraphs_test.rb +0 -562
  189. data/test/parser_test.rb +0 -742
  190. data/test/paths_test.rb +0 -395
  191. data/test/preamble_test.rb +0 -173
  192. data/test/reader_test.rb +0 -2161
  193. data/test/sections_test.rb +0 -3575
  194. data/test/substitutions_test.rb +0 -2066
  195. data/test/tables_test.rb +0 -2036
  196. data/test/test_helper.rb +0 -447
  197. data/test/text_test.rb +0 -309
@@ -1,34 +1,35 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
2
  module Asciidoctor
3
3
  class AbstractBlock < AbstractNode
4
- # Public: Get the Array of Asciidoctor::AbstractBlock sub-blocks for this block
4
+ # Public: Get the Array of {AbstractBlock} child blocks for this block. Only applies if content model is :compound.
5
5
  attr_reader :blocks
6
6
 
7
- # Public: Set the caption for this block
7
+ # Public: Set the caption for this block.
8
8
  attr_writer :caption
9
9
 
10
- # Public: The types of content that this block can accomodate
10
+ # Public: Describes the type of content this block accepts and how it should be converted. Acceptable values are:
11
+ # * :compound - this block contains other blocks
12
+ # * :simple - this block holds a paragraph of prose that receives normal substitutions
13
+ # * :verbatim - this block holds verbatim text (displayed "as is") that receives verbatim substitutions
14
+ # * :raw - this block holds unprocessed content passed directly to the output with no substitutions applied
15
+ # * :empty - this block has no content
11
16
  attr_accessor :content_model
12
17
 
13
- # Public: Set the Integer level of this Section or the Section level in which this Block resides
18
+ # Public: Set the Integer level of this {Section} or the level of the Section to which this {AbstractBlock} belongs.
14
19
  attr_accessor :level
15
20
 
16
- # Public: Get/Set the numeral of this block (if section, relative to parent, otherwise absolute)
17
- # Only assigned to section if automatic section numbering is enabled
18
- # Only assigned to formal block (block with title) if corresponding caption attribute is present
21
+ # Public: Get/Set the String numeral of this block (if section, relative to parent, otherwise absolute).
22
+ # Only assigned to section if automatic section numbering is enabled.
23
+ # Only assigned to formal block (block with title) if corresponding caption attribute is present.
19
24
  attr_accessor :numeral
20
25
 
21
- # Deprecated: Legacy property to get/set the numeral of this block
22
- alias number numeral
23
- alias number= numeral=
24
-
25
- # Public: Gets/Sets the location in the AsciiDoc source where this block begins
26
+ # Public: Gets/Sets the location in the AsciiDoc source where this block begins.
26
27
  attr_accessor :source_location
27
28
 
28
29
  # Public: Get/Set the String style (block type qualifier) for this block.
29
30
  attr_accessor :style
30
31
 
31
- # Public: Substitutions to be applied to content in this block
32
+ # Public: Substitutions to be applied to content in this block.
32
33
  attr_reader :subs
33
34
 
34
35
  def initialize parent, context, opts = {}
@@ -36,16 +37,15 @@ class AbstractBlock < AbstractNode
36
37
  @content_model = :compound
37
38
  @blocks = []
38
39
  @subs = []
39
- @id = @title = @title_converted = @caption = @numeral = @style = @default_subs = @source_location = nil
40
- if context == :document
41
- @level = 0
42
- elsif parent && context != :section
40
+ @id = @title = @caption = @numeral = @style = @default_subs = @source_location = nil
41
+ if context == :document || context == :section
42
+ @level = @next_section_index = 0
43
+ @next_section_ordinal = 1
44
+ elsif AbstractBlock === parent
43
45
  @level = parent.level
44
46
  else
45
47
  @level = nil
46
48
  end
47
- @next_section_index = 0
48
- @next_section_ordinal = 1
49
49
  end
50
50
 
51
51
  def block?
@@ -75,7 +75,7 @@ class AbstractBlock < AbstractNode
75
75
  converter.convert self
76
76
  end
77
77
 
78
- # Alias render to convert to maintain backwards compatibility
78
+ # Deprecated: Use {AbstractBlock#convert} instead.
79
79
  alias render convert
80
80
 
81
81
  # Public: Get the converted result of the child blocks by converting the
@@ -90,7 +90,7 @@ class AbstractBlock < AbstractNode
90
90
  #
91
91
  # context - the context Symbol context to assign to this block
92
92
  #
93
- # Returns the new context Symbol assigned to this block
93
+ # Returns the specified Symbol context
94
94
  def context= context
95
95
  @node_name = (@context = context).to_s
96
96
  end
@@ -101,10 +101,10 @@ class AbstractBlock < AbstractNode
101
101
  #
102
102
  # Examples
103
103
  #
104
- # block = Block.new(parent, :preamble, :content_model => :compound)
104
+ # block = Block.new(parent, :preamble, content_model: :compound)
105
105
  #
106
- # block << Block.new(block, :paragraph, :source => 'p1')
107
- # block << Block.new(block, :paragraph, :source => 'p2')
106
+ # block << Block.new(block, :paragraph, source: 'p1')
107
+ # block << Block.new(block, :paragraph, source: 'p2')
108
108
  # block.blocks?
109
109
  # # => true
110
110
  # block.blocks.size
@@ -124,28 +124,38 @@ class AbstractBlock < AbstractNode
124
124
  #
125
125
  # Returns A Boolean indicating whether this Block has block content
126
126
  def blocks?
127
- !@blocks.empty?
127
+ @blocks.empty? ? false : true
128
128
  end
129
129
 
130
130
  # Public: Check whether this block has any child Section objects.
131
131
  #
132
- # Only applies to Document and Section instances
132
+ # Acts an an abstract method that always returns false unless this block is an
133
+ # instance of Document or Section.
134
+ # Both Document and Section provide overrides for this method.
133
135
  #
134
- # Returns A [Boolean] to indicate whether this block has child Section objects
136
+ # Returns false
135
137
  def sections?
136
- @next_section_index > 0
138
+ false
137
139
  end
138
140
 
139
- # Public: Walk the document tree and find all block-level nodes that match
140
- # the specified selector (context, style, id, role, and/or custom filter).
141
+ # Deprecated: Legacy property to get the String or Integer numeral of this section.
142
+ def number
143
+ (Integer @numeral) rescue @numeral
144
+ end
145
+
146
+ # Deprecated: Legacy property to set the numeral of this section by coercing the value to a String.
147
+ def number= val
148
+ @numeral = val.to_s
149
+ end
150
+
151
+ # Public: Walk the document tree and find all block-level nodes that match the specified selector (context, style, id,
152
+ # role, and/or custom filter).
141
153
  #
142
- # If a Ruby block is given, it's treated as an supplemental filter. If the
143
- # filter returns true, the node is accepted and traversal continues. If the
144
- # filter returns false, the node is rejected, but traversal continues. If the
145
- # filter returns :skip, the node and all its descendants are rejected. If the
146
- # filter returns :skip_children, the node is accepted, but its descendants
147
- # are rejected. If no selector or filter block is supplied, all block-level
148
- # nodes in the tree are returned.
154
+ # If a Ruby block is given, it's applied as a supplemental filter. If the filter returns true (which implies :accept),
155
+ # the node is accepted and node traversal continues. If the filter returns false (which implies :skip), the node is
156
+ # skipped, but its children are still visited. If the filter returns :reject, the node and all its descendants are
157
+ # rejected. If the filter returns :prune, the node is accepted, but its descendants are rejected. If no selector
158
+ # or filter block is supplied, all block-level nodes in the tree are returned.
149
159
  #
150
160
  # Examples
151
161
  #
@@ -170,60 +180,16 @@ class AbstractBlock < AbstractNode
170
180
 
171
181
  alias query find_by
172
182
 
173
- # Internal: Performs the work for find_by, but does not handle the StopIteration exception.
174
- def find_by_internal selector = {}, result = [], &block
175
- if ((any_context = !(context_selector = selector[:context])) || context_selector == @context) &&
176
- (!(style_selector = selector[:style]) || style_selector == @style) &&
177
- (!(role_selector = selector[:role]) || (has_role? role_selector)) &&
178
- (!(id_selector = selector[:id]) || id_selector == @id)
179
- if id_selector
180
- result.replace block_given? ? ((yield self) ? [self] : []) : [self]
181
- raise ::StopIteration
182
- elsif block_given?
183
- if (verdict = yield self)
184
- case verdict
185
- when :skip_children
186
- result << self
187
- return result
188
- when :skip
189
- return result
190
- else
191
- result << self
192
- end
193
- end
194
- else
195
- result << self
196
- end
197
- end
198
-
199
- # process document header as a section if present
200
- if @context == :document && (any_context || context_selector == :section) && header?
201
- @header.find_by_internal selector, result, &block
202
- end
203
-
204
- unless context_selector == :document # optimization
205
- # yuck, dlist is a special case
206
- if @context == :dlist
207
- if any_context || context_selector != :section # optimization
208
- @blocks.flatten.each do |li|
209
- # NOTE the list item of a dlist can be nil, so we have to check
210
- li.find_by_internal selector, result, &block if li
211
- end
212
- end
213
- elsif
214
- @blocks.each do |b|
215
- next if (context_selector == :section && b.context != :section) # optimization
216
- b.find_by_internal selector, result, &block
217
- end
218
- end
219
- end
220
- result
221
- end
222
-
223
183
  # Move to the next adjacent block in document order. If the current block is the last
224
184
  # item in a list, this method will return the following sibling of the list block.
225
185
  def next_adjacent_block
226
- (sib = (p = parent).blocks[(p.blocks.find_index self) + 1]) ? sib : p.next_adjacent_block unless @context == :document
186
+ unless @context == :document
187
+ if (p = @parent).context == :dlist && @context == :list_item
188
+ (sib = p.items[(p.items.find_index {|terms, desc| (terms.include? self) || desc == self }) + 1]) ? sib : p.next_adjacent_block
189
+ else
190
+ (sib = p.blocks[(p.blocks.find_index self) + 1]) ? sib : p.next_adjacent_block
191
+ end
192
+ end
227
193
  end
228
194
 
229
195
  # Public: Get the Array of child Section objects
@@ -234,12 +200,12 @@ class AbstractBlock < AbstractNode
234
200
  #
235
201
  # doc << (sect1 = Section.new doc, 1)
236
202
  # sect1.title = 'Section 1'
237
- # para1 = Block.new sect1, :paragraph, :source => 'Paragraph 1'
238
- # para2 = Block.new sect1, :paragraph, :source => 'Paragraph 2'
203
+ # para1 = Block.new sect1, :paragraph, source: 'Paragraph 1'
204
+ # para2 = Block.new sect1, :paragraph, source: 'Paragraph 2'
239
205
  # sect1 << para1 << para2
240
206
  # sect1 << (sect1_1 = Section.new sect1, 2)
241
207
  # sect1_1.title = 'Section 1.1'
242
- # sect1_1 << (Block.new sect1_1, :paragraph, :source => 'Paragraph 3')
208
+ # sect1_1 << (Block.new sect1_1, :paragraph, source: 'Paragraph 3')
243
209
  # sect1.blocks?
244
210
  # # => true
245
211
  # sect1.blocks.size
@@ -264,6 +230,8 @@ class AbstractBlock < AbstractNode
264
230
  text = sub_specialchars text
265
231
  (ReplaceableTextRx.match? text) ? (sub_replacements text) : text
266
232
  end
233
+ else
234
+ ''
267
235
  end
268
236
  end
269
237
 
@@ -303,7 +271,7 @@ class AbstractBlock < AbstractNode
303
271
  ORDERED_LIST_KEYWORDS[list_type || @style]
304
272
  end
305
273
 
306
- # Public: Get the String title of this Block with title substitions applied
274
+ # Public: Get the String title of this Block with title substitutions applied
307
275
  #
308
276
  # The following substitutions are applied to block and section titles:
309
277
  #
@@ -318,7 +286,7 @@ class AbstractBlock < AbstractNode
318
286
  # Returns the converted String title for this Block, or nil if the source title is falsy
319
287
  def title
320
288
  # prevent substitutions from being applied to title multiple times
321
- @title_converted ? @converted_title : (@converted_title = (@title_converted = true) && @title && (apply_title_subs @title))
289
+ @converted_title ||= @title && (apply_title_subs @title)
322
290
  end
323
291
 
324
292
  # Public: A convenience method that checks whether the title of this block is defined.
@@ -330,9 +298,10 @@ class AbstractBlock < AbstractNode
330
298
 
331
299
  # Public: Set the String block title.
332
300
  #
333
- # Returns the new String title assigned to this Block
301
+ # Returns the specified String title
334
302
  def title= val
335
- @title, @title_converted = val, nil
303
+ @converted_title = nil
304
+ @title = val
336
305
  end
337
306
 
338
307
  # Public: A convenience method that checks whether the specified
@@ -376,17 +345,17 @@ class AbstractBlock < AbstractNode
376
345
  if (val = reftext) && !val.empty?
377
346
  val
378
347
  # NOTE xrefstyle only applies to blocks with a title and a caption or number
379
- elsif xrefstyle && @title && @caption
348
+ elsif xrefstyle && @title && !@caption.nil_or_empty?
380
349
  case xrefstyle
381
350
  when 'full'
382
- quoted_title = sprintf sub_quotes(@document.compat_mode ? %q(``%s'') : '"`%s`"'), title
383
- if @numeral && (prefix = @document.attributes[@context == :image ? 'figure-caption' : %(#{@context}-caption)])
351
+ quoted_title = sub_placeholder (sub_quotes @document.compat_mode ? %q(``%s'') : '"`%s`"'), title
352
+ if @numeral && (caption_attr_name = CAPTION_ATTRIBUTE_NAMES[@context]) && (prefix = @document.attributes[caption_attr_name])
384
353
  %(#{prefix} #{@numeral}, #{quoted_title})
385
354
  else
386
355
  %(#{@caption.chomp '. '}, #{quoted_title})
387
356
  end
388
357
  when 'short'
389
- if @numeral && (prefix = @document.attributes[@context == :image ? 'figure-caption' : %(#{@context}-caption)])
358
+ if @numeral && (caption_attr_name = CAPTION_ATTRIBUTE_NAMES[@context]) && (prefix = @document.attributes[caption_attr_name])
390
359
  %(#{prefix} #{@numeral})
391
360
  else
392
361
  @caption.chomp '. '
@@ -410,16 +379,16 @@ class AbstractBlock < AbstractNode
410
379
  # The parts of a complete caption are: <prefix> <number>. <title>
411
380
  # This partial caption represents the part the precedes the title.
412
381
  #
413
- # value - The explicit String caption to assign to this block (default: nil).
414
- # key - The String prefix for the caption and counter attribute names.
415
- # If not provided, the name of the context for this block is used.
416
- # (default: nil)
382
+ # value - The String caption to assign to this block or nil to use document attribute.
383
+ # caption_context - The Symbol context to use when resolving caption-related attributes. If not provided, the name of
384
+ # the context for this block is used. Only certain contexts allow the caption to be looked up.
385
+ # (default: @context)
417
386
  #
418
387
  # Returns nothing.
419
- def assign_caption value = nil, key = nil
388
+ def assign_caption value, caption_context = @context
420
389
  unless @caption || !@title || (@caption = value || @document.attributes['caption'])
421
- if (prefix = @document.attributes[%(#{key ||= @context}-caption)])
422
- @caption = %(#{prefix} #{@numeral = @document.increment_and_store_counter "#{key}-number", self}. )
390
+ if (attr_name = CAPTION_ATTRIBUTE_NAMES[caption_context]) && (prefix = @document.attributes[attr_name])
391
+ @caption = %(#{prefix} #{@numeral = @document.increment_and_store_counter %(#{caption_context}-number), self}. )
423
392
  nil
424
393
  end
425
394
  end
@@ -440,16 +409,12 @@ class AbstractBlock < AbstractNode
440
409
  if (like = section.numbered)
441
410
  if (sectname = section.sectname) == 'appendix'
442
411
  section.numeral = @document.counter 'appendix-number', 'A'
443
- if (caption = @document.attributes['appendix-caption'])
444
- section.caption = %(#{caption} #{section.numeral}: )
445
- else
446
- section.caption = %(#{section.numeral}. )
447
- end
412
+ section.caption = (caption = @document.attributes['appendix-caption']) ? %(#{caption} #{section.numeral}: ) : %(#{section.numeral}. )
448
413
  # NOTE currently chapters in a book doctype are sequential even for multi-part books (see #979)
449
414
  elsif sectname == 'chapter' || like == :chapter
450
- section.numeral = @document.counter 'chapter-number', 1
415
+ section.numeral = (@document.counter 'chapter-number', 1).to_s
451
416
  else
452
- section.numeral = @next_section_ordinal
417
+ section.numeral = sectname == 'part' ? (Helpers.int_to_roman @next_section_ordinal) : @next_section_ordinal.to_s
453
418
  @next_section_ordinal += 1
454
419
  end
455
420
  end
@@ -477,35 +442,76 @@ class AbstractBlock < AbstractNode
477
442
  end
478
443
  end
479
444
 
480
- # stage the Enumerable mixin until we're sure we've got it right
481
- =begin
482
- include ::Enumerable
445
+ protected
483
446
 
484
- # Public: Yield the block on this block node and all its descendant
485
- # block node children to satisfy the Enumerable contract.
486
- #
487
- # Returns nothing
488
- def each &block
489
- # yucky, dlist is a special case
490
- if @context == :dlist
491
- @blocks.flatten.each &block
492
- else
493
- #yield self.header if @context == :document && header?
494
- @blocks.each &block
447
+ # Internal: Performs the work for find_by, but does not handle the StopIteration exception.
448
+ def find_by_internal selector = {}, result = [], &block
449
+ if ((any_context = (context_selector = selector[:context]) ? nil : true) || context_selector == @context) &&
450
+ (!(style_selector = selector[:style]) || style_selector == @style) &&
451
+ (!(role_selector = selector[:role]) || (has_role? role_selector)) &&
452
+ (!(id_selector = selector[:id]) || id_selector == @id)
453
+ if block_given?
454
+ if (verdict = yield self)
455
+ case verdict
456
+ when :prune
457
+ result << self
458
+ raise ::StopIteration if id_selector
459
+ return result
460
+ when :reject
461
+ raise ::StopIteration if id_selector
462
+ return result
463
+ when :stop
464
+ raise ::StopIteration
465
+ else
466
+ result << self
467
+ raise ::StopIteration if id_selector
468
+ end
469
+ elsif id_selector
470
+ raise ::StopIteration
471
+ end
472
+ else
473
+ result << self
474
+ raise ::StopIteration if id_selector
475
+ end
495
476
  end
496
- end
497
-
498
- #--
499
- # TODO is there a way to make this lazy?
500
- def each_recursive &block
501
- block = lambda {|node| node } unless block_given?
502
- results = []
503
- self.each do |node|
504
- results << block.call(node)
505
- results.concat(node.each_recursive(&block)) if ::Enumerable === node
477
+ case @context
478
+ when :document
479
+ unless context_selector == :document
480
+ # process document header as a section, if present
481
+ if header? && (any_context || context_selector == :section)
482
+ @header.find_by_internal selector, result, &block
483
+ end
484
+ @blocks.each do |b|
485
+ next if context_selector == :section && b.context != :section # optimization
486
+ b.find_by_internal selector, result, &block
487
+ end
488
+ end
489
+ when :dlist
490
+ # dlist has different structure than other blocks
491
+ if any_context || context_selector != :section # optimization
492
+ # NOTE the list item of a dlist can be nil, so we have to check
493
+ @blocks.flatten.each {|b| b.find_by_internal selector, result, &block if b }
494
+ end
495
+ when :table
496
+ if selector[:traverse_documents]
497
+ rows.head.each {|r| r.each {|c| c.find_by_internal selector, result, &block } }
498
+ selector = selector.merge context: :document if context_selector == :inner_document
499
+ (rows.body + rows.foot).each do |r|
500
+ r.each do |c|
501
+ c.find_by_internal selector, result, &block
502
+ c.inner_document.find_by_internal selector, result, &block if c.style == :asciidoc
503
+ end
504
+ end
505
+ else
506
+ (rows.head + rows.body + rows.foot).each {|r| r.each {|c| c.find_by_internal selector, result, &block } }
507
+ end
508
+ else
509
+ @blocks.each do |b|
510
+ next if context_selector == :section && b.context != :section # optimization
511
+ b.find_by_internal selector, result, &block
512
+ end
506
513
  end
507
- block_given? ? results : results.to_enum
514
+ result
508
515
  end
509
- =end
510
516
  end
511
517
  end