asciidoctor 1.5.8 → 2.0.0.rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,1560 +0,0 @@
1
- # encoding: UTF-8
2
- unless defined? ASCIIDOCTOR_PROJECT_DIR
3
- $: << File.dirname(__FILE__); $:.uniq!
4
- require 'test_helper'
5
- end
6
-
7
- class ExtensionsInitTest < Minitest::Test
8
- def test_autoload
9
- doc = empty_document
10
- refute doc.extensions?, 'Extensions should not be enabled by default'
11
-
12
- begin
13
- # NOTE trigger extensions to autoload by registering empty group
14
- Asciidoctor::Extensions.register do
15
- end
16
- rescue; end
17
-
18
- doc = empty_document
19
- assert doc.extensions?, 'Extensions should be enabled after being autoloaded'
20
-
21
- self.class.remove_tests self.class
22
- ensure
23
- Asciidoctor::Extensions.unregister_all
24
- end
25
- self
26
- end.new(nil).test_autoload
27
-
28
- class SamplePreprocessor < Asciidoctor::Extensions::Preprocessor
29
- def process doc, reader
30
- nil
31
- end
32
- end
33
-
34
- class SampleIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
35
- end
36
-
37
- class SampleDocinfoProcessor < Asciidoctor::Extensions::DocinfoProcessor
38
- end
39
-
40
- # NOTE intentionally using the deprecated name
41
- class SampleTreeprocessor < Asciidoctor::Extensions::Treeprocessor
42
- def process document
43
- nil
44
- end
45
- end
46
- SampleTreeProcessor = SampleTreeprocessor
47
-
48
- class SamplePostprocessor < Asciidoctor::Extensions::Postprocessor
49
- end
50
-
51
- class SampleBlock < Asciidoctor::Extensions::BlockProcessor
52
- end
53
-
54
- class SampleBlockMacro < Asciidoctor::Extensions::BlockMacroProcessor
55
- end
56
-
57
- class SampleInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
58
- end
59
-
60
- class ScrubHeaderPreprocessor < Asciidoctor::Extensions::Preprocessor
61
- def process doc, reader
62
- lines = reader.lines
63
- skipped = []
64
- while !lines.empty? && !lines.first.start_with?('=')
65
- skipped << lines.shift
66
- reader.advance
67
- end
68
- doc.set_attr 'skipped', (skipped * "\n")
69
- reader
70
- end
71
- end
72
-
73
- class BoilerplateTextIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
74
- def handles? target
75
- target.end_with? '.txt'
76
- end
77
-
78
- def process document, reader, target, attributes
79
- case target
80
- when 'lorem-ipsum.txt'
81
- content = ["Lorem ipsum dolor sit amet...\n"]
82
- reader.push_include content, target, target, 1, attributes
83
- else
84
- nil
85
- end
86
- end
87
- end
88
-
89
- class ReplaceAuthorTreeProcessor < Asciidoctor::Extensions::TreeProcessor
90
- def process document
91
- document.attributes['firstname'] = 'Ghost'
92
- document.attributes['author'] = 'Ghost Writer'
93
- document
94
- end
95
- end
96
-
97
- class ReplaceTreeTreeProcessor < Asciidoctor::Extensions::TreeProcessor
98
- def process document
99
- if document.doctitle == 'Original Document'
100
- Asciidoctor.load %(== Replacement Document\nReplacement Author\n\ncontent)
101
- else
102
- document
103
- end
104
- end
105
- end
106
-
107
- class SelfSigningTreeProcessor < Asciidoctor::Extensions::TreeProcessor
108
- def process document
109
- document << (create_paragraph document, self.class.name, {})
110
- nil
111
- end
112
- end
113
-
114
- class StripAttributesPostprocessor < Asciidoctor::Extensions::Postprocessor
115
- def process document, output
116
- output.gsub(/<(\w+).*?>/m, "<\\1>")
117
- end
118
- end
119
-
120
- class UppercaseBlock < Asciidoctor::Extensions::BlockProcessor; use_dsl
121
- named :yell
122
- bound_to :paragraph
123
- parses_content_as :simple
124
- def process parent, reader, attributes
125
- create_paragraph parent, reader.lines.map(&:upcase), attributes
126
- end
127
- end
128
-
129
- class SnippetMacro < Asciidoctor::Extensions::BlockMacroProcessor
130
- def process parent, target, attributes
131
- create_pass_block parent, %(<script src="http://example.com/#{target}.js?_mode=#{attributes['mode']}"></script>), {}, :content_model => :raw
132
- end
133
- end
134
-
135
- class TemperatureMacro < Asciidoctor::Extensions::InlineMacroProcessor; use_dsl
136
- named :degrees
137
- resolves_attributes '1:units', 'precision=1'
138
- def process parent, target, attributes
139
- units = attributes['units'] || (parent.document.attr 'temperature-unit', 'C')
140
- precision = attributes['precision'].to_i
141
- c = target.to_f
142
- case units
143
- when 'C'
144
- %(#{round_with_precision c, precision} &#176;C)
145
- when 'F'
146
- %(#{round_with_precision c * 1.8 + 32, precision} &#176;F)
147
- else
148
- raise ::ArgumentError, %(Unknown temperature units: #{units})
149
- end
150
- end
151
-
152
- if (::Numeric.instance_method :round).arity == 0
153
- def round_with_precision value, precision = 0
154
- if precision == 0
155
- value.round
156
- else
157
- factor = 10 ** precision
158
- if precision < 0
159
- (value * factor).round.div factor
160
- else
161
- (value * factor).round.fdiv factor
162
- end
163
- end
164
- end
165
- else
166
- def round_with_precision value, precision = 0
167
- value.round precision
168
- end
169
- end
170
- end
171
-
172
- class MetaRobotsDocinfoProcessor < Asciidoctor::Extensions::DocinfoProcessor
173
- def process document
174
- '<meta name="robots" content="index,follow">'
175
- end
176
- end
177
-
178
- class MetaAppDocinfoProcessor < Asciidoctor::Extensions::DocinfoProcessor; use_dsl
179
- at_location :head
180
-
181
- def process document
182
- '<meta name="application-name" content="Asciidoctor App">'
183
- end
184
- end
185
-
186
- class SampleExtensionGroup < Asciidoctor::Extensions::Group
187
- def activate registry
188
- registry.document.attributes['activate-method-called'] = ''
189
- registry.preprocessor SamplePreprocessor
190
- end
191
- end
192
-
193
- def create_cat_in_sink_block_macro
194
- Asciidoctor::Extensions.create do
195
- block_macro do
196
- named :cat_in_sink
197
- process do |parent, target, attrs|
198
- image_attrs = {}
199
- unless target.nil_or_empty?
200
- image_attrs['target'] = %(cat-in-sink-day-#{target}.png)
201
- end
202
- if (title = attrs.delete 'title')
203
- image_attrs['title'] = title
204
- end
205
- if (alt = attrs.delete 1)
206
- image_attrs['alt'] = alt
207
- end
208
- create_image_block parent, image_attrs
209
- end
210
- end
211
- end
212
- end
213
-
214
- context 'Extensions' do
215
- context 'Register' do
216
- test 'should not activate registry if no extension groups are registered' do
217
- assert defined? Asciidoctor::Extensions
218
- doc = empty_document
219
- refute doc.extensions?, 'Extensions should not be enabled if not groups are registered'
220
- end
221
-
222
- test 'should register extension group class' do
223
- begin
224
- Asciidoctor::Extensions.register :sample, SampleExtensionGroup
225
- refute_nil Asciidoctor::Extensions.groups
226
- assert_equal 1, Asciidoctor::Extensions.groups.size
227
- assert_equal SampleExtensionGroup, Asciidoctor::Extensions.groups[:sample]
228
- ensure
229
- Asciidoctor::Extensions.unregister_all
230
- end
231
- end
232
-
233
- test 'should self register extension group class' do
234
- begin
235
- SampleExtensionGroup.register :sample
236
- refute_nil Asciidoctor::Extensions.groups
237
- assert_equal 1, Asciidoctor::Extensions.groups.size
238
- assert_equal SampleExtensionGroup, Asciidoctor::Extensions.groups[:sample]
239
- ensure
240
- Asciidoctor::Extensions.unregister_all
241
- end
242
- end
243
-
244
- test 'should register extension group from class name' do
245
- begin
246
- Asciidoctor::Extensions.register :sample, 'SampleExtensionGroup'
247
- refute_nil Asciidoctor::Extensions.groups
248
- assert_equal 1, Asciidoctor::Extensions.groups.size
249
- assert_equal SampleExtensionGroup, Asciidoctor::Extensions.groups[:sample]
250
- ensure
251
- Asciidoctor::Extensions.unregister_all
252
- end
253
- end
254
-
255
- test 'should register extension group from instance' do
256
- begin
257
- Asciidoctor::Extensions.register :sample, SampleExtensionGroup.new
258
- refute_nil Asciidoctor::Extensions.groups
259
- assert_equal 1, Asciidoctor::Extensions.groups.size
260
- assert_kind_of SampleExtensionGroup, Asciidoctor::Extensions.groups[:sample]
261
- ensure
262
- Asciidoctor::Extensions.unregister_all
263
- end
264
- end
265
-
266
- test 'should register extension block' do
267
- begin
268
- Asciidoctor::Extensions.register :sample do
269
- end
270
- refute_nil Asciidoctor::Extensions.groups
271
- assert_equal 1, Asciidoctor::Extensions.groups.size
272
- assert_kind_of Proc, Asciidoctor::Extensions.groups[:sample]
273
- ensure
274
- Asciidoctor::Extensions.unregister_all
275
- end
276
- end
277
-
278
- test 'should coerce group name to symbol when registering' do
279
- begin
280
- Asciidoctor::Extensions.register 'sample', SampleExtensionGroup
281
- refute_nil Asciidoctor::Extensions.groups
282
- assert_equal 1, Asciidoctor::Extensions.groups.size
283
- assert_equal SampleExtensionGroup, Asciidoctor::Extensions.groups[:sample]
284
- ensure
285
- Asciidoctor::Extensions.unregister_all
286
- end
287
- end
288
-
289
- test 'should unregister extension group by symbol name' do
290
- begin
291
- Asciidoctor::Extensions.register :sample, SampleExtensionGroup
292
- refute_nil Asciidoctor::Extensions.groups
293
- assert_equal 1, Asciidoctor::Extensions.groups.size
294
- Asciidoctor::Extensions.unregister :sample
295
- assert_equal 0, Asciidoctor::Extensions.groups.size
296
- ensure
297
- Asciidoctor::Extensions.unregister_all
298
- end
299
- end
300
-
301
- test 'should unregister extension group by string name' do
302
- begin
303
- Asciidoctor::Extensions.register :sample, SampleExtensionGroup
304
- refute_nil Asciidoctor::Extensions.groups
305
- assert_equal 1, Asciidoctor::Extensions.groups.size
306
- Asciidoctor::Extensions.unregister 'sample'
307
- assert_equal 0, Asciidoctor::Extensions.groups.size
308
- ensure
309
- Asciidoctor::Extensions.unregister_all
310
- end
311
- end
312
-
313
- test 'should unregister multiple extension groups by name' do
314
- begin
315
- Asciidoctor::Extensions.register :sample1, SampleExtensionGroup
316
- Asciidoctor::Extensions.register :sample2, SampleExtensionGroup
317
- refute_nil Asciidoctor::Extensions.groups
318
- assert_equal 2, Asciidoctor::Extensions.groups.size
319
- Asciidoctor::Extensions.unregister :sample1, :sample2
320
- assert_equal 0, Asciidoctor::Extensions.groups.size
321
- ensure
322
- Asciidoctor::Extensions.unregister_all
323
- end
324
- end
325
-
326
- test 'should get class for top-level class name' do
327
- clazz = Asciidoctor::Extensions.class_for_name 'String'
328
- refute_nil clazz
329
- assert_equal String, clazz
330
- end
331
-
332
- test 'should get class for class name in module' do
333
- clazz = Asciidoctor::Extensions.class_for_name 'Asciidoctor::Document'
334
- refute_nil clazz
335
- assert_equal Asciidoctor::Document, clazz
336
- end
337
-
338
- test 'should get class for class name resolved from root' do
339
- clazz = Asciidoctor::Extensions.class_for_name '::Asciidoctor::Document'
340
- refute_nil clazz
341
- assert_equal Asciidoctor::Document, clazz
342
- end
343
-
344
- test 'should raise exception if cannot find class for name' do
345
- begin
346
- Asciidoctor::Extensions.class_for_name 'InvalidModule::InvalidClass'
347
- flunk 'Expecting RuntimeError to be raised'
348
- rescue NameError => e
349
- assert_equal 'Could not resolve class for name: InvalidModule::InvalidClass', e.message
350
- end
351
- end
352
-
353
- test 'should raise exception if constant name is invalid' do
354
- begin
355
- Asciidoctor::Extensions.class_for_name 'foobar'
356
- flunk 'Expecting RuntimeError to be raised'
357
- rescue NameError => e
358
- assert_equal 'Could not resolve class for name: foobar', e.message
359
- end
360
- end
361
-
362
- test 'should raise exception if class not found in scope' do
363
- begin
364
- Asciidoctor::Extensions.class_for_name 'Asciidoctor::Extensions::String'
365
- flunk 'Expecting RuntimeError to be raised'
366
- rescue NameError => e
367
- assert_equal 'Could not resolve class for name: Asciidoctor::Extensions::String', e.message
368
- end
369
- end
370
-
371
- test 'should raise exception if name resolves to module' do
372
- begin
373
- Asciidoctor::Extensions.class_for_name 'Asciidoctor::Extensions'
374
- flunk 'Expecting RuntimeError to be raised'
375
- rescue NameError => e
376
- assert_equal 'Could not resolve class for name: Asciidoctor::Extensions', e.message
377
- end
378
- end
379
-
380
- test 'should resolve class if class is given' do
381
- clazz = Asciidoctor::Extensions.resolve_class Asciidoctor::Document
382
- refute_nil clazz
383
- assert_equal Asciidoctor::Document, clazz
384
- end
385
-
386
- test 'should resolve class if class from string' do
387
- clazz = Asciidoctor::Extensions.resolve_class 'Asciidoctor::Document'
388
- refute_nil clazz
389
- assert_equal Asciidoctor::Document, clazz
390
- end
391
-
392
- test 'should not resolve class if not in scope' do
393
- begin
394
- Asciidoctor::Extensions.resolve_class 'Asciidoctor::Extensions::String'
395
- flunk 'Expecting RuntimeError to be raised'
396
- rescue NameError => e
397
- assert_equal 'Could not resolve class for name: Asciidoctor::Extensions::String', e.message
398
- end
399
- end
400
-
401
- test 'should raise NameError if extension class cannot be resolved from string' do
402
- begin
403
- Asciidoctor::Extensions.register do
404
- block 'foobar'
405
- end
406
- empty_document
407
- flunk 'Expecting RuntimeError to be raised'
408
- rescue NameError => e
409
- assert_equal 'Could not resolve class for name: foobar', e.message
410
- ensure
411
- Asciidoctor::Extensions.unregister_all
412
- end
413
- end
414
-
415
- test 'should allow standalone registry to be created but not registered' do
416
- registry = Asciidoctor::Extensions.create 'sample' do
417
- block do
418
- named :whisper
419
- bound_to :paragraph
420
- parses_content_as :simple
421
- def process parent, reader, attributes
422
- create_paragraph parent, reader.lines.map(&:downcase), attributes
423
- end
424
- end
425
- end
426
-
427
- assert_instance_of Asciidoctor::Extensions::Registry, registry
428
- refute_nil registry.groups
429
- assert_equal 1, registry.groups.size
430
- assert_equal 'sample', registry.groups.keys.first
431
- assert_equal 0, Asciidoctor::Extensions.groups.size
432
- end
433
- end
434
-
435
- context 'Activate' do
436
- test 'should call activate on extension group class' do
437
- begin
438
- doc = Asciidoctor::Document.new
439
- Asciidoctor::Extensions.register :sample, SampleExtensionGroup
440
- registry = Asciidoctor::Extensions::Registry.new
441
- registry.activate doc
442
- assert doc.attr? 'activate-method-called'
443
- assert registry.preprocessors?
444
- ensure
445
- Asciidoctor::Extensions.unregister_all
446
- end
447
- end
448
-
449
- test 'should invoke extension block' do
450
- begin
451
- doc = Asciidoctor::Document.new
452
- Asciidoctor::Extensions.register do
453
- @document.attributes['block-called'] = ''
454
- preprocessor SamplePreprocessor
455
- end
456
- registry = Asciidoctor::Extensions::Registry.new
457
- registry.activate doc
458
- assert doc.attr? 'block-called'
459
- assert registry.preprocessors?
460
- ensure
461
- Asciidoctor::Extensions.unregister_all
462
- end
463
- end
464
-
465
- test 'should create registry in Document if extensions are loaded' do
466
- begin
467
- SampleExtensionGroup.register
468
- doc = Asciidoctor::Document.new
469
- assert doc.extensions?
470
- assert_kind_of Asciidoctor::Extensions::Registry, doc.extensions
471
- ensure
472
- Asciidoctor::Extensions.unregister_all
473
- end
474
-
475
- end
476
- end
477
-
478
- context 'Instantiate' do
479
- test 'should instantiate preprocessors' do
480
- registry = Asciidoctor::Extensions::Registry.new
481
- registry.preprocessor SamplePreprocessor
482
- registry.activate Asciidoctor::Document.new
483
- assert registry.preprocessors?
484
- extensions = registry.preprocessors
485
- assert_equal 1, extensions.size
486
- assert_kind_of Asciidoctor::Extensions::ProcessorExtension, extensions.first
487
- assert_kind_of SamplePreprocessor, extensions.first.instance
488
- assert_kind_of Method, extensions.first.process_method
489
- end
490
-
491
- test 'should instantiate include processors' do
492
- registry = Asciidoctor::Extensions::Registry.new
493
- registry.include_processor SampleIncludeProcessor
494
- registry.activate Asciidoctor::Document.new
495
- assert registry.include_processors?
496
- extensions = registry.include_processors
497
- assert_equal 1, extensions.size
498
- assert_kind_of Asciidoctor::Extensions::ProcessorExtension, extensions.first
499
- assert_kind_of SampleIncludeProcessor, extensions.first.instance
500
- assert_kind_of Method, extensions.first.process_method
501
- end
502
-
503
- test 'should instantiate docinfo processors' do
504
- registry = Asciidoctor::Extensions::Registry.new
505
- registry.docinfo_processor SampleDocinfoProcessor
506
- registry.activate Asciidoctor::Document.new
507
- assert registry.docinfo_processors?
508
- assert registry.docinfo_processors?(:head)
509
- extensions = registry.docinfo_processors
510
- assert_equal 1, extensions.size
511
- assert_kind_of Asciidoctor::Extensions::ProcessorExtension, extensions.first
512
- assert_kind_of SampleDocinfoProcessor, extensions.first.instance
513
- assert_kind_of Method, extensions.first.process_method
514
- end
515
-
516
- # NOTE intentionally using the legacy names
517
- test 'should instantiate tree processors' do
518
- registry = Asciidoctor::Extensions::Registry.new
519
- registry.treeprocessor SampleTreeprocessor
520
- registry.activate Asciidoctor::Document.new
521
- assert registry.treeprocessors?
522
- extensions = registry.treeprocessors
523
- assert_equal 1, extensions.size
524
- assert_kind_of Asciidoctor::Extensions::ProcessorExtension, extensions.first
525
- assert_kind_of SampleTreeprocessor, extensions.first.instance
526
- assert_kind_of Method, extensions.first.process_method
527
- end
528
-
529
- test 'should instantiate postprocessors' do
530
- registry = Asciidoctor::Extensions::Registry.new
531
- registry.postprocessor SamplePostprocessor
532
- registry.activate Asciidoctor::Document.new
533
- assert registry.postprocessors?
534
- extensions = registry.postprocessors
535
- assert_equal 1, extensions.size
536
- assert_kind_of Asciidoctor::Extensions::ProcessorExtension, extensions.first
537
- assert_kind_of SamplePostprocessor, extensions.first.instance
538
- assert_kind_of Method, extensions.first.process_method
539
- end
540
-
541
- test 'should instantiate block processor' do
542
- registry = Asciidoctor::Extensions::Registry.new
543
- registry.block SampleBlock, :sample
544
- registry.activate Asciidoctor::Document.new
545
- assert registry.blocks?
546
- assert registry.registered_for_block? :sample, :paragraph
547
- extension = registry.find_block_extension :sample
548
- assert_kind_of Asciidoctor::Extensions::ProcessorExtension, extension
549
- assert_kind_of SampleBlock, extension.instance
550
- assert_kind_of Method, extension.process_method
551
- end
552
-
553
- test 'should not match block processor for unsupported context' do
554
- registry = Asciidoctor::Extensions::Registry.new
555
- registry.block SampleBlock, :sample
556
- registry.activate Asciidoctor::Document.new
557
- refute registry.registered_for_block? :sample, :sidebar
558
- end
559
-
560
- test 'should instantiate block macro processor' do
561
- registry = Asciidoctor::Extensions::Registry.new
562
- registry.block_macro SampleBlockMacro, 'sample'
563
- registry.activate Asciidoctor::Document.new
564
- assert registry.block_macros?
565
- assert registry.registered_for_block_macro? 'sample'
566
- extension = registry.find_block_macro_extension 'sample'
567
- assert_kind_of Asciidoctor::Extensions::ProcessorExtension, extension
568
- assert_kind_of SampleBlockMacro, extension.instance
569
- assert_kind_of Method, extension.process_method
570
- end
571
-
572
- test 'should instantiate inline macro processor' do
573
- registry = Asciidoctor::Extensions::Registry.new
574
- registry.inline_macro SampleInlineMacro, 'sample'
575
- registry.activate Asciidoctor::Document.new
576
- assert registry.inline_macros?
577
- assert registry.registered_for_inline_macro? 'sample'
578
- extension = registry.find_inline_macro_extension 'sample'
579
- assert_kind_of Asciidoctor::Extensions::ProcessorExtension, extension
580
- assert_kind_of SampleInlineMacro, extension.instance
581
- assert_kind_of Method, extension.process_method
582
- end
583
-
584
- test 'should allow processors to be registered by a string name' do
585
- registry = Asciidoctor::Extensions::Registry.new
586
- registry.preprocessor 'SamplePreprocessor'
587
- registry.activate Asciidoctor::Document.new
588
- assert registry.preprocessors?
589
- extensions = registry.preprocessors
590
- assert_equal 1, extensions.size
591
- assert_kind_of Asciidoctor::Extensions::ProcessorExtension, extensions.first
592
- end
593
- end
594
-
595
- context 'Integration' do
596
- test 'can provide extension registry as an option' do
597
- registry = Asciidoctor::Extensions.create do
598
- tree_processor SampleTreeProcessor
599
- end
600
-
601
- doc = document_from_string %(= Document Title\n\ncontent), :extension_registry => registry
602
- refute_nil doc.extensions
603
- assert_equal 1, doc.extensions.groups.size
604
- assert doc.extensions.tree_processors?
605
- assert_equal 1, doc.extensions.tree_processors.size
606
- assert_equal 0, Asciidoctor::Extensions.groups.size
607
- end
608
-
609
- # NOTE I'm not convinced we want to continue to support this use case
610
- test 'can provide extension registry created without any groups as option' do
611
- registry = Asciidoctor::Extensions.create
612
- registry.tree_processor SampleTreeProcessor
613
-
614
- doc = document_from_string %(= Document Title\n\ncontent), :extension_registry => registry
615
- refute_nil doc.extensions
616
- assert_equal 0, doc.extensions.groups.size
617
- assert doc.extensions.tree_processors?
618
- assert_equal 1, doc.extensions.tree_processors.size
619
- assert_equal 0, Asciidoctor::Extensions.groups.size
620
- end
621
-
622
- test 'can provide extensions proc as option' do
623
- doc = document_from_string %(= Document Title\n\ncontent), :extensions => proc {
624
- tree_processor SampleTreeProcessor
625
- }
626
- refute_nil doc.extensions
627
- assert_equal 1, doc.extensions.groups.size
628
- assert doc.extensions.tree_processors?
629
- assert_equal 1, doc.extensions.tree_processors.size
630
- assert_equal 0, Asciidoctor::Extensions.groups.size
631
- end
632
-
633
- test 'should invoke preprocessors before parsing document' do
634
- input = <<-EOS
635
- junk line
636
-
637
- = Document Title
638
-
639
- sample content
640
- EOS
641
-
642
- begin
643
- Asciidoctor::Extensions.register do
644
- preprocessor ScrubHeaderPreprocessor
645
- end
646
-
647
- doc = document_from_string input
648
- assert doc.attr? 'skipped'
649
- assert_equal 'junk line', (doc.attr 'skipped').strip
650
- assert doc.has_header?
651
- assert_equal 'Document Title', doc.doctitle
652
- ensure
653
- Asciidoctor::Extensions.unregister_all
654
- end
655
- end
656
-
657
- test 'should invoke include processor to process include macro' do
658
- input = <<-EOS
659
- before
660
-
661
- include::lorem-ipsum.txt[]
662
-
663
- after
664
- EOS
665
-
666
- begin
667
- Asciidoctor::Extensions.register do
668
- include_processor BoilerplateTextIncludeProcessor
669
- end
670
-
671
- result = convert_string input, :safe => :server
672
- assert_css '.paragraph > p', result, 3
673
- assert_includes result, 'before'
674
- assert_includes result, 'Lorem ipsum'
675
- assert_includes result, 'after'
676
- ensure
677
- Asciidoctor::Extensions.unregister_all
678
- end
679
- end
680
-
681
- test 'should call include processor to process include directive' do
682
- input = <<-EOS
683
- first line
684
-
685
- include::include-file.asciidoc[]
686
-
687
- last line
688
- EOS
689
-
690
- registry = Asciidoctor::Extensions.create do
691
- include_processor do
692
- handles? do |target|
693
- target == 'include-file.asciidoc'
694
- end
695
-
696
- process do |doc, reader, target, attributes|
697
- # demonstrate that push_include normalizes endlines
698
- content = ["include target:: #{target}\n", "\n", "middle line\n"]
699
- reader.push_include content, target, target, 1, attributes
700
- end
701
- end
702
- end
703
- # Safe Mode is not required here
704
- document = empty_document :base_dir => testdir, :extension_registry => registry
705
- reader = Asciidoctor::PreprocessorReader.new document, input, nil, :normalize => true
706
- lines = []
707
- lines << reader.read_line
708
- lines << reader.read_line
709
- lines << reader.read_line
710
- assert_equal 'include target:: include-file.asciidoc', lines.last
711
- assert_equal 'include-file.asciidoc: line 2', reader.line_info
712
- while reader.has_more_lines?
713
- lines << reader.read_line
714
- end
715
- source = lines * ::Asciidoctor::LF
716
- assert_match(/^include target:: include-file.asciidoc$/, source)
717
- assert_match(/^middle line$/, source)
718
- end
719
-
720
- test 'should invoke tree processors after parsing document' do
721
- input = <<-EOS
722
- = Document Title
723
- Doc Writer
724
-
725
- content
726
- EOS
727
-
728
- begin
729
- Asciidoctor::Extensions.register do
730
- tree_processor ReplaceAuthorTreeProcessor
731
- end
732
-
733
- doc = document_from_string input
734
- assert_equal 'Ghost Writer', doc.author
735
- ensure
736
- Asciidoctor::Extensions.unregister_all
737
- end
738
- end
739
-
740
- test 'should set source_location on document before invoking tree processors' do
741
- begin
742
- Asciidoctor::Extensions.register do
743
- tree_processor do
744
- process do |doc|
745
- para = create_paragraph doc.blocks.last.parent, %(file: #{doc.file}, lineno: #{doc.lineno}), {}
746
- doc << para
747
- end
748
- end
749
- end
750
-
751
- sample_doc = fixture_path 'sample.asciidoc'
752
- doc = Asciidoctor.load_file sample_doc, :sourcemap => true
753
- assert_includes doc.convert, 'file: sample.asciidoc, lineno: 1'
754
- ensure
755
- Asciidoctor::Extensions.unregister_all
756
- end
757
- end
758
-
759
- test 'should allow tree processor to replace tree' do
760
- input = <<-EOS
761
- = Original Document
762
- Doc Writer
763
-
764
- content
765
- EOS
766
-
767
- begin
768
- Asciidoctor::Extensions.register do
769
- tree_processor ReplaceTreeTreeProcessor
770
- end
771
-
772
- doc = document_from_string input
773
- assert_equal 'Replacement Document', doc.doctitle
774
- ensure
775
- Asciidoctor::Extensions.unregister_all
776
- end
777
- end
778
-
779
- test 'should honor block title assigned in tree processor' do
780
- input = <<-EOS
781
- = Document Title
782
- :!example-caption:
783
-
784
- .Old block title
785
- ====
786
- example block content
787
- ====
788
- EOS
789
-
790
- old_title = nil
791
- begin
792
- Asciidoctor::Extensions.register do
793
- tree_processor do
794
- process do |doc|
795
- ex = (doc.find_by :context => :example)[0]
796
- old_title = ex.title
797
- ex.title = 'New block title'
798
- end
799
- end
800
- end
801
-
802
- doc = document_from_string input
803
- assert_equal 'Old block title', old_title
804
- assert_equal 'New block title', (doc.find_by :context => :example)[0].title
805
- ensure
806
- Asciidoctor::Extensions.unregister_all
807
- end
808
- end
809
-
810
- test 'should be able to register preferred tree processor' do
811
- begin
812
- Asciidoctor::Extensions.register do
813
- tree_processor do
814
- process do |doc|
815
- doc << (create_paragraph doc, 'd', {})
816
- nil
817
- end
818
- end
819
-
820
- tree_processor do
821
- prefer
822
- process do |doc|
823
- doc << (create_paragraph doc, 'c', {})
824
- nil
825
- end
826
- end
827
-
828
- prefer :tree_processor do
829
- process do |doc|
830
- doc << (create_paragraph doc, 'b', {})
831
- nil
832
- end
833
- end
834
-
835
- prefer tree_processor {
836
- process do |doc|
837
- doc << (create_paragraph doc, 'a', {})
838
- nil
839
- end
840
- }
841
-
842
- prefer :tree_processor, SelfSigningTreeProcessor
843
- end
844
-
845
- (doc = empty_document).convert
846
- assert_equal %w(SelfSigningTreeProcessor a b c d), doc.blocks.map {|b| b.lines[0] }
847
- ensure
848
- Asciidoctor::Extensions.unregister_all
849
- end
850
- end
851
-
852
- test 'should invoke postprocessors after converting document' do
853
- input = <<-EOS
854
- * one
855
- * two
856
- * three
857
- EOS
858
-
859
- begin
860
- Asciidoctor::Extensions.register do
861
- postprocessor StripAttributesPostprocessor
862
- end
863
-
864
- output = convert_string input
865
- refute_match(/<div class="ulist">/, output)
866
- ensure
867
- Asciidoctor::Extensions.unregister_all
868
- end
869
- end
870
-
871
- test 'should invoke processor for custom block' do
872
- input = <<-EOS
873
- [yell]
874
- Hi there!
875
- EOS
876
-
877
- begin
878
- Asciidoctor::Extensions.register do
879
- block UppercaseBlock
880
- end
881
-
882
- output = convert_string_to_embedded input
883
- assert_xpath '//p', output, 1
884
- assert_xpath '//p[text()="HI THERE!"]', output, 1
885
- ensure
886
- Asciidoctor::Extensions.unregister_all
887
- end
888
- end
889
-
890
- test 'should invoke processor for custom block in an AsciiDoc table cell' do
891
- input = <<-EOS
892
- |===
893
- a|
894
- [yell]
895
- Hi there!
896
- |===
897
- EOS
898
-
899
- begin
900
- Asciidoctor::Extensions.register do
901
- block UppercaseBlock
902
- end
903
-
904
- output = convert_string_to_embedded input
905
- assert_xpath '/table//p', output, 1
906
- assert_xpath '/table//p[text()="HI THERE!"]', output, 1
907
- ensure
908
- Asciidoctor::Extensions.unregister_all
909
- end
910
- end
911
-
912
- test 'should pass cloaked context in attributes passed to process method of custom block' do
913
- input = <<-EOS
914
- [custom]
915
- ****
916
- sidebar
917
- ****
918
- EOS
919
-
920
- cloaked_context = nil
921
- begin
922
- Asciidoctor::Extensions.register do
923
- block :custom do
924
- on_context :sidebar
925
- process do |doc, reader, attrs|
926
- cloaked_context = attrs['cloaked-context']
927
- nil
928
- end
929
- end
930
- end
931
-
932
- convert_string_to_embedded input
933
- assert_equal :sidebar, cloaked_context
934
- ensure
935
- Asciidoctor::Extensions.unregister_all
936
- end
937
- end
938
-
939
- test 'should invoke processor for custom block macro' do
940
- input = <<-EOS
941
- snippet::12345[mode=edit]
942
- EOS
943
-
944
- begin
945
- Asciidoctor::Extensions.register do
946
- block_macro SnippetMacro, :snippet
947
- end
948
-
949
- output = convert_string_to_embedded input
950
- assert_includes output, '<script src="http://example.com/12345.js?_mode=edit"></script>'
951
- ensure
952
- Asciidoctor::Extensions.unregister_all
953
- end
954
- end
955
-
956
- test 'should substitute attributes in target of custom block macro' do
957
- input = <<-EOS
958
- snippet::{gist-id}[mode=edit]
959
- EOS
960
-
961
- begin
962
- Asciidoctor::Extensions.register do
963
- block_macro SnippetMacro, :snippet
964
- end
965
-
966
- output = convert_string_to_embedded input, :attributes => { 'gist-id' => '12345' }
967
- assert_includes output, '<script src="http://example.com/12345.js?_mode=edit"></script>'
968
- ensure
969
- Asciidoctor::Extensions.unregister_all
970
- end
971
- end
972
-
973
- test 'should drop block macro line if target references missing attribute and attribute-missing is drop-line' do
974
- input = <<-EOS
975
- [.rolename]
976
- snippet::{gist-ns}12345[mode=edit]
977
-
978
- following paragraph
979
- EOS
980
-
981
- begin
982
- Asciidoctor::Extensions.register do
983
- block_macro SnippetMacro, :snippet
984
- end
985
-
986
- doc, output = nil, nil
987
- using_memory_logger do |logger|
988
- doc = document_from_string input, :attributes => { 'attribute-missing' => 'drop-line' }
989
- assert_equal 1, doc.blocks.size
990
- assert_equal :paragraph, doc.blocks[0].context
991
- output = doc.convert
992
- assert_message logger, :WARN, 'dropping line containing reference to missing attribute: gist-ns'
993
- end
994
- assert_css '.paragraph', output, 1
995
- assert_css '.rolename', output, 0
996
- ensure
997
- Asciidoctor::Extensions.unregister_all
998
- end
999
- end
1000
-
1001
- test 'should invoke processor for custom block macro in an AsciiDoc table cell' do
1002
- input = <<-EOS
1003
- |===
1004
- a|message::hi[]
1005
- |===
1006
- EOS
1007
-
1008
- begin
1009
- Asciidoctor::Extensions.register do
1010
- block_macro :message do
1011
- process do |parent, target, attrs|
1012
- create_paragraph parent, target.upcase, {}
1013
- end
1014
- end
1015
- end
1016
-
1017
- output = convert_string_to_embedded input
1018
- assert_xpath '/table//p[text()="HI"]', output, 1
1019
- ensure
1020
- Asciidoctor::Extensions.unregister_all
1021
- end
1022
- end
1023
-
1024
- test 'should match short form of block macro' do
1025
- input = <<-EOS
1026
- custom-toc::[]
1027
- EOS
1028
-
1029
- resolved_target = nil
1030
-
1031
- begin
1032
- Asciidoctor::Extensions.register do
1033
- block_macro do
1034
- named 'custom-toc'
1035
- process do |parent, target, attrs|
1036
- resolved_target = target
1037
- create_pass_block parent, '<!-- custom toc goes here -->', {}, :content_model => :raw
1038
- end
1039
- end
1040
- end
1041
-
1042
- output = convert_string_to_embedded input
1043
- assert_equal '<!-- custom toc goes here -->', output
1044
- assert_equal '', resolved_target
1045
- ensure
1046
- Asciidoctor::Extensions.unregister_all
1047
- end
1048
- end
1049
-
1050
- test 'should fail to convert if name of block macro is illegal' do
1051
- input = 'illegal name::target[]'
1052
-
1053
- begin
1054
- Asciidoctor::Extensions.register do
1055
- block_macro do
1056
- named 'illegal name'
1057
- process do |parent, target, attrs|
1058
- nil
1059
- end
1060
- end
1061
- end
1062
-
1063
- assert_raises ArgumentError do
1064
- convert_string_to_embedded input
1065
- end
1066
- ensure
1067
- Asciidoctor::Extensions.unregister_all
1068
- end
1069
- end
1070
-
1071
- test 'should be able to set header attribute in block macro processor' do
1072
- begin
1073
- Asciidoctor::Extensions.register do
1074
- block_macro do
1075
- named :attribute
1076
- resolves_attributes '1:value'
1077
- process do |parent, target, attrs|
1078
- parent.document.set_attr target, attrs['value']
1079
- nil
1080
- end
1081
- end
1082
- block_macro do
1083
- named :header_attribute
1084
- resolves_attributes '1:value'
1085
- process do |parent, target, attrs|
1086
- parent.document.set_header_attribute target, attrs['value']
1087
- nil
1088
- end
1089
- end
1090
- end
1091
- input = <<-EOS
1092
- attribute::yin[yang]
1093
-
1094
- header_attribute::foo[bar]
1095
- EOS
1096
- doc = document_from_string input
1097
- assert_nil doc.attr 'yin'
1098
- assert_equal 'bar', (doc.attr 'foo')
1099
- ensure
1100
- Asciidoctor::Extensions.unregister_all
1101
- end
1102
- end
1103
-
1104
- test 'should invoke processor for custom inline macro' do
1105
- begin
1106
- Asciidoctor::Extensions.register do
1107
- inline_macro TemperatureMacro, :deg
1108
- end
1109
-
1110
- output = convert_string_to_embedded 'Room temperature is deg:25[C,precision=0].', :attributes => { 'temperature-unit' => 'F' }
1111
- assert_includes output, 'Room temperature is 25 &#176;C.'
1112
-
1113
- output = convert_string_to_embedded 'Normal body temperature is deg:37[].', :attributes => { 'temperature-unit' => 'F' }
1114
- assert_includes output, 'Normal body temperature is 98.6 &#176;F.'
1115
- ensure
1116
- Asciidoctor::Extensions.unregister_all
1117
- end
1118
- end
1119
-
1120
- test 'should resolve regexp for inline macro lazily' do
1121
- begin
1122
- Asciidoctor::Extensions.register do
1123
- inline_macro do
1124
- named :label
1125
- with_format :short
1126
- resolves_attributes false
1127
- process do |parent, target|
1128
- %(<label>#{target}</label>)
1129
- end
1130
- end
1131
- end
1132
-
1133
- output = convert_string_to_embedded 'label:[Checkbox]'
1134
- assert_includes output, '<label>Checkbox</label>'
1135
- ensure
1136
- Asciidoctor::Extensions.unregister_all
1137
- end
1138
- end
1139
-
1140
- test 'should assign captures correctly for inline macros' do
1141
- begin
1142
- Asciidoctor::Extensions.register do
1143
- inline_macro do
1144
- named :short_attributes
1145
- with_format :short
1146
- resolves_attributes '1:name'
1147
- process do |parent, target, attrs|
1148
- %(target=#{target.inspect}, attributes=#{attrs.sort_by {|k, _| k.to_s }.inspect})
1149
- end
1150
- end
1151
-
1152
- inline_macro do
1153
- named :short_text
1154
- with_format :short
1155
- resolves_attributes false
1156
- process do |parent, target, attrs|
1157
- %(target=#{target.inspect}, attributes=#{attrs.sort_by {|k, _| k.to_s }.inspect})
1158
- end
1159
- end
1160
-
1161
- inline_macro do
1162
- named :'full-attributes'
1163
- resolves_attributes '1:name' => nil
1164
- process do |parent, target, attrs|
1165
- %(target=#{target.inspect}, attributes=#{attrs.sort_by {|k, _| k.to_s }.inspect})
1166
- end
1167
- end
1168
-
1169
- inline_macro do
1170
- named :'full-text'
1171
- resolves_attributes false
1172
- process do |parent, target, attrs|
1173
- %(target=#{target.inspect}, attributes=#{attrs.sort_by {|k, _| k.to_s }.inspect})
1174
- end
1175
- end
1176
-
1177
- inline_macro do
1178
- named :@short_match
1179
- matching %r/@(\w+)/
1180
- resolves_attributes false
1181
- process do |parent, target, attrs|
1182
- %(target=#{target.inspect}, attributes=#{attrs.sort_by {|k, _| k.to_s }.inspect})
1183
- end
1184
- end
1185
- end
1186
-
1187
- input = <<-EOS
1188
- [subs=normal]
1189
- ++++
1190
- short_attributes:[]
1191
- short_attributes:[value,key=val]
1192
- short_text:[]
1193
- short_text:[[text\\]]
1194
- full-attributes:target[]
1195
- full-attributes:target[value,key=val]
1196
- full-text:target[]
1197
- full-text:target[[text\\]]
1198
- @target
1199
- ++++
1200
- EOS
1201
- expected = <<-EOS.chomp
1202
- target="", attributes=[]
1203
- target="value,key=val", attributes=[[1, "value"], ["key", "val"], ["name", "value"]]
1204
- target="", attributes=[["text", ""]]
1205
- target="[text]", attributes=[["text", "[text]"]]
1206
- target="target", attributes=[]
1207
- target="target", attributes=[[1, "value"], ["key", "val"], ["name", "value"]]
1208
- target="target", attributes=[["text", ""]]
1209
- target="target", attributes=[["text", "[text]"]]
1210
- target="target", attributes=[]
1211
- EOS
1212
- output = convert_string_to_embedded input
1213
- assert_equal expected, output
1214
- ensure
1215
- Asciidoctor::Extensions.unregister_all
1216
- end
1217
- end
1218
-
1219
- test 'should invoke convert on return value if value is an inline node' do
1220
- begin
1221
- Asciidoctor::Extensions.register do
1222
- inline_macro do
1223
- named :mention
1224
- resolves_attributes false
1225
- process do |parent, target, attrs|
1226
- if (text = attrs['text']).empty?
1227
- text = %(@#{target})
1228
- end
1229
- create_anchor parent, text, :type => :link, :target => %(https://github.com/#{target})
1230
- end
1231
- end
1232
- end
1233
-
1234
- output = convert_string_to_embedded 'mention:mojavelinux[Dan]'
1235
- assert_includes output, '<a href="https://github.com/mojavelinux">Dan</a>'
1236
- ensure
1237
- Asciidoctor::Extensions.unregister_all
1238
- end
1239
- end
1240
-
1241
- test 'should not carry over attributes if block processor returns nil' do
1242
- begin
1243
- Asciidoctor::Extensions.register do
1244
- block do
1245
- named 'skip-me'
1246
- on_context :paragraph
1247
- parses_content_as :raw
1248
- process do |parent, reader, attrs|
1249
- nil
1250
- end
1251
- end
1252
- end
1253
- input = <<-EOS
1254
- .unused title
1255
- [skip-me]
1256
- not shown
1257
-
1258
- --
1259
- shown
1260
- --
1261
- EOS
1262
- doc = document_from_string input
1263
- assert_equal 1, doc.blocks.size
1264
- assert_nil doc.blocks[0].attributes['title']
1265
- ensure
1266
- Asciidoctor::Extensions.unregister_all
1267
- end
1268
- end
1269
-
1270
- test 'should not invoke process method or carry over attributes if block processor declares skip content model' do
1271
- begin
1272
- process_method_called = false
1273
- Asciidoctor::Extensions.register do
1274
- block do
1275
- named :ignore
1276
- on_context :paragraph
1277
- parses_content_as :skip
1278
- process do |parent, reader, attrs|
1279
- process_method_called = true
1280
- nil
1281
- end
1282
- end
1283
- end
1284
- input = <<-EOS
1285
- .unused title
1286
- [ignore]
1287
- not shown
1288
-
1289
- --
1290
- shown
1291
- --
1292
- EOS
1293
- doc = document_from_string input
1294
- refute process_method_called
1295
- assert_equal 1, doc.blocks.size
1296
- assert_nil doc.blocks[0].attributes['title']
1297
- ensure
1298
- Asciidoctor::Extensions.unregister_all
1299
- end
1300
- end
1301
-
1302
- test 'should pass attributes by value to block processor' do
1303
- begin
1304
- Asciidoctor::Extensions.register do
1305
- block do
1306
- named :foo
1307
- on_context :paragraph
1308
- parses_content_as :raw
1309
- process do |parent, reader, attrs|
1310
- original_attrs = attrs.dup
1311
- attrs.delete('title')
1312
- create_paragraph parent, reader.read_lines, original_attrs.merge('id' => 'value')
1313
- end
1314
- end
1315
- end
1316
- input = <<-EOS
1317
- .title
1318
- [foo]
1319
- content
1320
- EOS
1321
- doc = document_from_string input
1322
- assert_equal 1, doc.blocks.size
1323
- assert_equal 'title', doc.blocks[0].attributes['title']
1324
- assert_equal 'value', doc.blocks[0].id
1325
- ensure
1326
- Asciidoctor::Extensions.unregister_all
1327
- end
1328
- end
1329
-
1330
- test 'parse_content should not share attributes between parsed blocks' do
1331
- begin
1332
- Asciidoctor::Extensions.register do
1333
- block do
1334
- named :wrap
1335
- on_context :open
1336
- process do |parent, reader, attrs|
1337
- wrap = create_open_block parent, nil, attrs
1338
- parse_content wrap, reader.read_lines
1339
- end
1340
- end
1341
- end
1342
- input = <<-EOS
1343
- [wrap]
1344
- --
1345
- [foo=bar]
1346
- ====
1347
- content
1348
- ====
1349
-
1350
- [baz=qux]
1351
- ====
1352
- content
1353
- ====
1354
- --
1355
- EOS
1356
- doc = document_from_string input
1357
- assert_equal 1, doc.blocks.size
1358
- wrap = doc.blocks[0]
1359
- assert_equal 2, wrap.blocks.size
1360
- assert_equal 2, wrap.blocks[0].attributes.size
1361
- assert_equal 2, wrap.blocks[1].attributes.size
1362
- assert_nil wrap.blocks[1].attributes['foo']
1363
- ensure
1364
- Asciidoctor::Extensions.unregister_all
1365
- end
1366
- end
1367
-
1368
- test 'create_section should set up all section properties' do
1369
- begin
1370
- sect = nil
1371
- Asciidoctor::Extensions.register do
1372
- block_macro do
1373
- named :sect
1374
- process do |parent, target, attrs|
1375
- opts = (level = attrs.delete 'level') ? { :level => level.to_i } : {}
1376
- attrs['id'] = false if attrs['id'] == 'false'
1377
- parent = parent.parent if parent.context == :preamble
1378
- sect = create_section parent, 'Section Title', attrs, opts
1379
- nil
1380
- end
1381
- end
1382
- end
1383
-
1384
- input_tpl = <<-EOS
1385
- = Document Title
1386
- :doctype: book
1387
- :sectnums:
1388
-
1389
- sect::[%s]
1390
- EOS
1391
-
1392
- {
1393
- '' => ['chapter', 1, false, true, '_section_title'],
1394
- 'level=0' => ['part', 0, false, false, '_section_title'],
1395
- 'level=0,alt' => ['part', 0, false, true, '_section_title', { 'partnums' => '' }],
1396
- 'level=0,style=appendix' => ['appendix', 1, true, true, '_section_title'],
1397
- 'style=appendix' => ['appendix', 1, true, true, '_section_title'],
1398
- 'style=glossary' => ['glossary', 1, true, false, '_section_title'],
1399
- 'style=glossary,alt' => ['glossary', 1, true, :chapter, '_section_title', { 'sectnums' => 'all' }],
1400
- 'style=abstract' => ['chapter', 1, false, true, '_section_title'],
1401
- 'id=section-title' => ['chapter', 1, false, true, 'section-title'],
1402
- 'id=false' => ['chapter', 1, false, true, nil]
1403
- }.each do |attrlist, (expect_sectname, expect_level, expect_special, expect_numbered, expect_id, extra_attrs)|
1404
- input = input_tpl % attrlist
1405
- document_from_string input, :safe => :server, :attributes => extra_attrs
1406
- assert_equal expect_sectname, sect.sectname
1407
- assert_equal expect_level, sect.level
1408
- assert_equal expect_special, sect.special
1409
- assert_equal expect_numbered, sect.numbered
1410
- if expect_id
1411
- assert_equal expect_id, sect.id
1412
- else
1413
- assert_nil sect.id
1414
- end
1415
- end
1416
- ensure
1417
- Asciidoctor::Extensions.unregister_all
1418
- end
1419
- end
1420
-
1421
- test 'should add docinfo to document' do
1422
- input = <<-EOS
1423
- = Document Title
1424
-
1425
- sample content
1426
- EOS
1427
-
1428
- begin
1429
- Asciidoctor::Extensions.register do
1430
- docinfo_processor MetaRobotsDocinfoProcessor
1431
- end
1432
-
1433
- doc = document_from_string input, :safe => :server
1434
- assert_equal '<meta name="robots" content="index,follow">', doc.docinfo
1435
- ensure
1436
- Asciidoctor::Extensions.unregister_all
1437
- end
1438
- end
1439
-
1440
- test 'should add multiple docinfo to document' do
1441
- input = <<-EOS
1442
- = Document Title
1443
-
1444
- sample content
1445
- EOS
1446
-
1447
- begin
1448
- Asciidoctor::Extensions.register do
1449
- docinfo_processor MetaAppDocinfoProcessor
1450
- docinfo_processor MetaRobotsDocinfoProcessor, :position => :>>
1451
- docinfo_processor do
1452
- at_location :footer
1453
- process do |doc|
1454
- '<script><!-- analytics code --></script>'
1455
- end
1456
- end
1457
- end
1458
-
1459
- doc = document_from_string input, :safe => :server
1460
- assert_equal '<meta name="robots" content="index,follow">
1461
- <meta name="application-name" content="Asciidoctor App">', doc.docinfo
1462
- assert_equal '<script><!-- analytics code --></script>', doc.docinfo(:footer)
1463
- ensure
1464
- Asciidoctor::Extensions.unregister_all
1465
- end
1466
- end
1467
-
1468
- test 'should append docinfo to document' do
1469
- begin
1470
- Asciidoctor::Extensions.register do
1471
- docinfo_processor MetaRobotsDocinfoProcessor
1472
- end
1473
- sample_input_path = fixture_path('basic.asciidoc')
1474
-
1475
- output = Asciidoctor.convert_file sample_input_path, :to_file => false,
1476
- :header_footer => true,
1477
- :safe => Asciidoctor::SafeMode::SERVER,
1478
- :attributes => {'docinfo' => ''}
1479
- refute_empty output
1480
- assert_css 'script[src="modernizr.js"]', output, 1
1481
- assert_css 'meta[name="robots"]', output, 1
1482
- assert_css 'meta[http-equiv="imagetoolbar"]', output, 0
1483
- ensure
1484
- Asciidoctor::Extensions.unregister_all
1485
- end
1486
- end
1487
-
1488
- test 'should return extension instance after registering' do
1489
- begin
1490
- exts = []
1491
- Asciidoctor::Extensions.register do
1492
- exts.push preprocessor SamplePreprocessor
1493
- exts.push include_processor SampleIncludeProcessor
1494
- exts.push tree_processor SampleTreeProcessor
1495
- exts.push docinfo_processor SampleDocinfoProcessor
1496
- exts.push postprocessor SamplePostprocessor
1497
- end
1498
- empty_document
1499
- exts.each do |ext|
1500
- assert_kind_of Asciidoctor::Extensions::ProcessorExtension, ext
1501
- end
1502
- ensure
1503
- Asciidoctor::Extensions.unregister_all
1504
- end
1505
- end
1506
-
1507
- test 'should raise an exception if mandatory target attribute is not provided for image block' do
1508
- input = <<-EOS
1509
- cat_in_sink::[]
1510
- EOS
1511
- exception = assert_raises ArgumentError do
1512
- convert_string_to_embedded input, :extension_registry => create_cat_in_sink_block_macro
1513
- end
1514
- assert_match(/target attribute is required/, exception.message)
1515
- end
1516
-
1517
- test 'should assign alt attribute to image block if alt is not provided' do
1518
- input = <<-EOS
1519
- cat_in_sink::25[]
1520
- EOS
1521
- doc = document_from_string input, :header_footer => false, :extension_registry => create_cat_in_sink_block_macro
1522
- image = doc.blocks[0]
1523
- assert_equal 'cat in sink day 25', (image.attr 'alt')
1524
- assert_equal 'cat in sink day 25', (image.attr 'default-alt')
1525
- output = doc.convert
1526
- assert_includes output, '<img src="cat-in-sink-day-25.png" alt="cat in sink day 25">'
1527
- end
1528
-
1529
- test 'should create an image block if mandatory attributes are provided' do
1530
- input = <<-EOS
1531
- cat_in_sink::30[cat in sink (yes)]
1532
- EOS
1533
- doc = document_from_string input, :header_footer => false, :extension_registry => create_cat_in_sink_block_macro
1534
- image = doc.blocks[0]
1535
- assert_equal 'cat in sink (yes)', (image.attr 'alt')
1536
- refute(image.attr? 'default-alt')
1537
- output = doc.convert
1538
- assert_includes output, '<img src="cat-in-sink-day-30.png" alt="cat in sink (yes)">'
1539
- end
1540
-
1541
- test 'should not assign caption on image block if title is not set on custom block macro' do
1542
- input = <<-EOS
1543
- cat_in_sink::30[]
1544
- EOS
1545
- doc = document_from_string input, :header_footer => false, :extension_registry => create_cat_in_sink_block_macro
1546
- output = doc.convert
1547
- assert_xpath '/*[@class="imageblock"]/*[@class="title"]', output, 0
1548
- end
1549
-
1550
- test 'should assign caption on image block if title is set on custom block macro' do
1551
- input = <<-EOS
1552
- .Cat in Sink?
1553
- cat_in_sink::30[]
1554
- EOS
1555
- doc = document_from_string input, :header_footer => false, :extension_registry => create_cat_in_sink_block_macro
1556
- output = doc.convert
1557
- assert_xpath '/*[@class="imageblock"]/*[@class="title"][text()="Figure 1. Cat in Sink?"]', output, 1
1558
- end
1559
- end
1560
- end