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,3870 +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
- context 'Blocks' do
8
- default_logger = Asciidoctor::LoggerManager.logger
9
-
10
- setup do
11
- Asciidoctor::LoggerManager.logger = (@logger = Asciidoctor::MemoryLogger.new)
12
- end
13
-
14
- teardown do
15
- Asciidoctor::LoggerManager.logger = default_logger
16
- end
17
-
18
- context 'Layout Breaks' do
19
- test 'horizontal rule' do
20
- %w(''' '''' '''''').each do |line|
21
- output = convert_string_to_embedded line
22
- assert_includes output, '<hr>'
23
- end
24
- end
25
-
26
- test '< 3 chars does not make horizontal rule' do
27
- %w(' '').each do |line|
28
- output = convert_string_to_embedded line
29
- refute_includes output, '<hr>'
30
- assert_includes output, %(<p>#{line}</p>)
31
- end
32
- end
33
-
34
- test 'mixed chars does not make horizontal rule' do
35
- [%q(''<), %q('''<), %q(' ' ')].each do |line|
36
- output = convert_string_to_embedded line
37
- refute_includes output, '<hr>'
38
- assert_includes output, %(<p>#{line.sub '<', '&lt;'}</p>)
39
- end
40
- end
41
-
42
- test 'horizontal rule between blocks' do
43
- output = convert_string_to_embedded %(Block above\n\n'''\n\nBlock below)
44
- assert_xpath '/hr', output, 1
45
- assert_xpath '/hr/preceding-sibling::*', output, 1
46
- assert_xpath '/hr/following-sibling::*', output, 1
47
- end
48
-
49
- test 'page break' do
50
- output = convert_string_to_embedded %(page 1\n\n<<<\n\npage 2)
51
- assert_xpath '/*[translate(@style, ";", "")="page-break-after: always"]', output, 1
52
- assert_xpath '/*[translate(@style, ";", "")="page-break-after: always"]/preceding-sibling::div/p[text()="page 1"]', output, 1
53
- assert_xpath '/*[translate(@style, ";", "")="page-break-after: always"]/following-sibling::div/p[text()="page 2"]', output, 1
54
- end
55
- end
56
-
57
- context 'Comments' do
58
- test 'line comment between paragraphs offset by blank lines' do
59
- input = <<-EOS
60
- first paragraph
61
-
62
- // line comment
63
-
64
- second paragraph
65
- EOS
66
- output = convert_string_to_embedded input
67
- refute_match(/line comment/, output)
68
- assert_xpath '//p', output, 2
69
- end
70
-
71
- test 'adjacent line comment between paragraphs' do
72
- input = <<-EOS
73
- first line
74
- // line comment
75
- second line
76
- EOS
77
- output = convert_string_to_embedded input
78
- refute_match(/line comment/, output)
79
- assert_xpath '//p', output, 1
80
- assert_xpath "//p[1][text()='first line\nsecond line']", output, 1
81
- end
82
-
83
- test 'comment block between paragraphs offset by blank lines' do
84
- input = <<-EOS
85
- first paragraph
86
-
87
- ////
88
- block comment
89
- ////
90
-
91
- second paragraph
92
- EOS
93
- output = convert_string_to_embedded input
94
- refute_match(/block comment/, output)
95
- assert_xpath '//p', output, 2
96
- end
97
-
98
- test 'comment block between paragraphs offset by blank lines inside delimited block' do
99
- input = <<-EOS
100
- ====
101
- first paragraph
102
-
103
- ////
104
- block comment
105
- ////
106
-
107
- second paragraph
108
- ====
109
- EOS
110
- output = convert_string_to_embedded input
111
- refute_match(/block comment/, output)
112
- assert_xpath '//p', output, 2
113
- end
114
-
115
- test 'adjacent comment block between paragraphs' do
116
- input = <<-EOS
117
- first paragraph
118
- ////
119
- block comment
120
- ////
121
- second paragraph
122
- EOS
123
- output = convert_string_to_embedded input
124
- refute_match(/block comment/, output)
125
- assert_xpath '//p', output, 2
126
- end
127
-
128
- test "can convert with block comment at end of document with trailing endlines" do
129
- input = <<-EOS
130
- paragraph
131
-
132
- ////
133
- block comment
134
- ////
135
-
136
-
137
- EOS
138
- output = convert_string_to_embedded input
139
- refute_match(/block comment/, output)
140
- end
141
-
142
- test "trailing endlines after block comment at end of document does not create paragraph" do
143
- input = <<-EOS
144
- paragraph
145
-
146
- ////
147
- block comment
148
- ////
149
-
150
-
151
- EOS
152
- d = document_from_string input
153
- assert_equal 1, d.blocks.size
154
- assert_xpath '//p', d.convert, 1
155
- end
156
-
157
- test 'line starting with three slashes should not be line comment' do
158
- input = <<-EOS
159
- /// not a line comment
160
- EOS
161
-
162
- output = convert_string_to_embedded input
163
- refute_empty output.strip, "Line should be emitted => #{input.rstrip}"
164
- end
165
-
166
- test 'preprocessor directives should not be processed within comment block within block metadata' do
167
- input = <<-EOS
168
- .sample title
169
- ////
170
- ifdef::asciidoctor[////]
171
- ////
172
- line should be shown
173
- EOS
174
-
175
- output = convert_string_to_embedded input
176
- assert_xpath '//p[text() = "line should be shown"]', output, 1
177
- end
178
-
179
- test 'preprocessor directives should not be processed within comment block' do
180
- input = <<-EOS
181
- dummy line
182
-
183
- ////
184
- ifdef::asciidoctor[////]
185
- ////
186
-
187
- line should be shown
188
- EOS
189
-
190
- output = convert_string_to_embedded input
191
- assert_xpath '//p[text() = "line should be shown"]', output, 1
192
- end
193
-
194
- test 'should warn if unterminated comment block is detected in body' do
195
- input = <<-EOS
196
- before comment block
197
-
198
- ////
199
- content that has been disabled
200
-
201
- supposed to be after comment block, except it got swallowed by block comment
202
- EOS
203
-
204
- convert_string_to_embedded input
205
- assert_message @logger, :WARN, '<stdin>: line 3: unterminated comment block', Hash
206
- end
207
-
208
- test 'should warn if unterminated comment block is detected inside another block' do
209
- input = <<-EOS
210
- before sidebar block
211
-
212
- ****
213
- ////
214
- content that has been disabled
215
- ****
216
-
217
- supposed to be after sidebar block, except it got swallowed by block comment
218
- EOS
219
-
220
- convert_string_to_embedded input
221
- assert_message @logger, :WARN, '<stdin>: line 4: unterminated comment block', Hash
222
- end
223
-
224
- # WARNING if first line of content is a directive, it will get interpretted before we know it's a comment block
225
- # it happens because we always look a line ahead...not sure what we can do about it
226
- test 'preprocessor directives should not be processed within comment open block' do
227
- input = <<-EOS
228
- [comment]
229
- --
230
- first line of comment
231
- ifdef::asciidoctor[--]
232
- line should not be shown
233
- --
234
-
235
- EOS
236
-
237
- output = convert_string_to_embedded input
238
- assert_xpath '//p', output, 0
239
- end
240
-
241
- # WARNING this assertion fails if the directive is the first line of the paragraph instead of the second
242
- # it happens because we always look a line ahead; not sure what we can do about it
243
- test 'preprocessor directives should not be processed on subsequent lines of a comment paragraph' do
244
- input = <<-EOS
245
- [comment]
246
- first line of content
247
- ifdef::asciidoctor[////]
248
-
249
- this line should be shown
250
- EOS
251
-
252
- output = convert_string_to_embedded input
253
- assert_xpath '//p[text() = "this line should be shown"]', output, 1
254
- end
255
-
256
- test 'comment style on open block should only skip block' do
257
- input = <<-EOS
258
- [comment]
259
- --
260
- skip
261
-
262
- this block
263
- --
264
-
265
- not this text
266
- EOS
267
- result = convert_string_to_embedded input
268
- assert_xpath '//p', result, 1
269
- assert_xpath '//p[text()="not this text"]', result, 1
270
- end
271
-
272
- test 'comment style on paragraph should only skip paragraph' do
273
- input = <<-EOS
274
- [comment]
275
- skip
276
- this paragraph
277
-
278
- not this text
279
- EOS
280
- result = convert_string_to_embedded input
281
- assert_xpath '//p', result, 1
282
- assert_xpath '//p[text()="not this text"]', result, 1
283
- end
284
-
285
- test 'comment style on paragraph should not cause adjacent block to be skipped' do
286
- input = <<-EOS
287
- [comment]
288
- skip
289
- this paragraph
290
- [example]
291
- not this text
292
- EOS
293
- result = convert_string_to_embedded input
294
- assert_xpath '/*[@class="exampleblock"]', result, 1
295
- assert_xpath '/*[@class="exampleblock"]//*[normalize-space(text())="not this text"]', result, 1
296
- end
297
-
298
- # NOTE this test verifies the nil return value of Parser#next_block
299
- test 'should not drop content that follows skipped content inside a delimited block' do
300
- input = <<-EOS
301
- ====
302
- paragraph
303
-
304
- [comment#idname]
305
- skip
306
-
307
- paragraph
308
- ====
309
- EOS
310
- result = convert_string_to_embedded input
311
- assert_xpath '/*[@class="exampleblock"]', result, 1
312
- assert_xpath '/*[@class="exampleblock"]//*[@class="paragraph"]', result, 2
313
- assert_xpath '//*[@class="paragraph"][@id="idname"]', result, 0
314
- end
315
- end
316
-
317
- context 'Quote and Verse Blocks' do
318
- test 'quote block with no attribution' do
319
- input = <<-EOS
320
- ____
321
- A famous quote.
322
- ____
323
- EOS
324
- output = convert_string input
325
- assert_css '.quoteblock', output, 1
326
- assert_css '.quoteblock > blockquote', output, 1
327
- assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
328
- assert_css '.quoteblock > .attribution', output, 0
329
- assert_xpath '//*[@class = "quoteblock"]//p[text() = "A famous quote."]', output, 1
330
- end
331
-
332
- test 'quote block with attribution' do
333
- input = <<-EOS
334
- [quote, Famous Person, Famous Book (1999)]
335
- ____
336
- A famous quote.
337
- ____
338
- EOS
339
- output = convert_string input
340
- assert_css '.quoteblock', output, 1
341
- assert_css '.quoteblock > blockquote', output, 1
342
- assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
343
- assert_css '.quoteblock > .attribution', output, 1
344
- assert_css '.quoteblock > .attribution > cite', output, 1
345
- assert_css '.quoteblock > .attribution > br + cite', output, 1
346
- assert_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]/cite[text() = "Famous Book (1999)"]', output, 1
347
- attribution = xmlnodes_at_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]', output, 1
348
- author = attribution.children.first
349
- assert_equal "#{decode_char 8212} Famous Person", author.text.strip
350
- end
351
-
352
- test 'quote block with attribute and id and role shorthand' do
353
- input = <<-EOS
354
- [quote#justice-to-all.solidarity, Martin Luther King, Jr.]
355
- ____
356
- Injustice anywhere is a threat to justice everywhere.
357
- ____
358
- EOS
359
-
360
- output = convert_string_to_embedded input
361
- assert_css '.quoteblock', output, 1
362
- assert_css '#justice-to-all.quoteblock.solidarity', output, 1
363
- assert_css '.quoteblock > .attribution', output, 1
364
- end
365
-
366
- test 'setting ID using style shorthand should not reset block style' do
367
- input = <<-EOS
368
- [quote]
369
- [#justice-to-all.solidarity, Martin Luther King, Jr.]
370
- ____
371
- Injustice anywhere is a threat to justice everywhere.
372
- ____
373
- EOS
374
-
375
- output = convert_string_to_embedded input
376
- assert_css '.quoteblock', output, 1
377
- assert_css '#justice-to-all.quoteblock.solidarity', output, 1
378
- assert_css '.quoteblock > .attribution', output, 1
379
- end
380
-
381
- test 'quote block with complex content' do
382
- input = <<-EOS
383
- ____
384
- A famous quote.
385
-
386
- NOTE: _That_ was inspiring.
387
- ____
388
- EOS
389
- output = convert_string input
390
- assert_css '.quoteblock', output, 1
391
- assert_css '.quoteblock > blockquote', output, 1
392
- assert_css '.quoteblock > blockquote > .paragraph', output, 1
393
- assert_css '.quoteblock > blockquote > .paragraph + .admonitionblock', output, 1
394
- end
395
-
396
- test 'quote block with attribution converted to DocBook' do
397
- input = <<-EOS
398
- [quote, Famous Person, Famous Book (1999)]
399
- ____
400
- A famous quote.
401
- ____
402
- EOS
403
- output = convert_string input, :backend => :docbook
404
- assert_css 'blockquote', output, 1
405
- assert_css 'blockquote > simpara', output, 1
406
- assert_css 'blockquote > attribution', output, 1
407
- assert_css 'blockquote > attribution > citetitle', output, 1
408
- assert_xpath '//blockquote/attribution/citetitle[text() = "Famous Book (1999)"]', output, 1
409
- attribution = xmlnodes_at_xpath '//blockquote/attribution', output, 1
410
- author = attribution.children.first
411
- assert_equal 'Famous Person', author.text.strip
412
- end
413
-
414
- test 'epigraph quote block with attribution converted to DocBook' do
415
- input = <<-EOS
416
- [.epigraph, Famous Person, Famous Book (1999)]
417
- ____
418
- A famous quote.
419
- ____
420
- EOS
421
- output = convert_string input, :backend => :docbook
422
- assert_css 'epigraph', output, 1
423
- assert_css 'epigraph > simpara', output, 1
424
- assert_css 'epigraph > attribution', output, 1
425
- assert_css 'epigraph > attribution > citetitle', output, 1
426
- assert_xpath '//epigraph/attribution/citetitle[text() = "Famous Book (1999)"]', output, 1
427
- attribution = xmlnodes_at_xpath '//epigraph/attribution', output, 1
428
- author = attribution.children.first
429
- assert_equal 'Famous Person', author.text.strip
430
- end
431
-
432
- test 'quote block using air quotes with no attribution' do
433
- input = <<-EOS
434
- ""
435
- A famous quote.
436
- ""
437
- EOS
438
- output = convert_string input
439
- assert_css '.quoteblock', output, 1
440
- assert_css '.quoteblock > blockquote', output, 1
441
- assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
442
- assert_css '.quoteblock > .attribution', output, 0
443
- assert_xpath '//*[@class = "quoteblock"]//p[text() = "A famous quote."]', output, 1
444
- end
445
-
446
- test 'markdown-style quote block with single paragraph and no attribution' do
447
- input = <<-EOS
448
- > A famous quote.
449
- > Some more inspiring words.
450
- EOS
451
- output = convert_string input
452
- assert_css '.quoteblock', output, 1
453
- assert_css '.quoteblock > blockquote', output, 1
454
- assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
455
- assert_css '.quoteblock > .attribution', output, 0
456
- assert_xpath %(//*[@class = "quoteblock"]//p[text() = "A famous quote.\nSome more inspiring words."]), output, 1
457
- end
458
-
459
- test 'lazy markdown-style quote block with single paragraph and no attribution' do
460
- input = <<-EOS
461
- > A famous quote.
462
- Some more inspiring words.
463
- EOS
464
- output = convert_string input
465
- assert_css '.quoteblock', output, 1
466
- assert_css '.quoteblock > blockquote', output, 1
467
- assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
468
- assert_css '.quoteblock > .attribution', output, 0
469
- assert_xpath %(//*[@class = "quoteblock"]//p[text() = "A famous quote.\nSome more inspiring words."]), output, 1
470
- end
471
-
472
- test 'markdown-style quote block with multiple paragraphs and no attribution' do
473
- input = <<-EOS
474
- > A famous quote.
475
- >
476
- > Some more inspiring words.
477
- EOS
478
- output = convert_string input
479
- assert_css '.quoteblock', output, 1
480
- assert_css '.quoteblock > blockquote', output, 1
481
- assert_css '.quoteblock > blockquote > .paragraph > p', output, 2
482
- assert_css '.quoteblock > .attribution', output, 0
483
- assert_xpath %((//*[@class = "quoteblock"]//p)[1][text() = "A famous quote."]), output, 1
484
- assert_xpath %((//*[@class = "quoteblock"]//p)[2][text() = "Some more inspiring words."]), output, 1
485
- end
486
-
487
- test 'markdown-style quote block with multiple blocks and no attribution' do
488
- input = <<-EOS
489
- > A famous quote.
490
- >
491
- > NOTE: Some more inspiring words.
492
- EOS
493
- output = convert_string input
494
- assert_css '.quoteblock', output, 1
495
- assert_css '.quoteblock > blockquote', output, 1
496
- assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
497
- assert_css '.quoteblock > blockquote > .admonitionblock', output, 1
498
- assert_css '.quoteblock > .attribution', output, 0
499
- assert_xpath %((//*[@class = "quoteblock"]//p)[1][text() = "A famous quote."]), output, 1
500
- assert_xpath %((//*[@class = "quoteblock"]//*[@class = "admonitionblock note"]//*[@class="content"])[1][normalize-space(text()) = "Some more inspiring words."]), output, 1
501
- end
502
-
503
- test 'markdown-style quote block with single paragraph and attribution' do
504
- input = <<-EOS
505
- > A famous quote.
506
- > Some more inspiring words.
507
- > -- Famous Person, Famous Source, Volume 1 (1999)
508
- EOS
509
- output = convert_string input
510
- assert_css '.quoteblock', output, 1
511
- assert_css '.quoteblock > blockquote', output, 1
512
- assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
513
- assert_xpath %(//*[@class = "quoteblock"]//p[text() = "A famous quote.\nSome more inspiring words."]), output, 1
514
- assert_css '.quoteblock > .attribution', output, 1
515
- assert_css '.quoteblock > .attribution > cite', output, 1
516
- assert_css '.quoteblock > .attribution > br + cite', output, 1
517
- assert_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]/cite[text() = "Famous Source, Volume 1 (1999)"]', output, 1
518
- attribution = xmlnodes_at_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]', output, 1
519
- author = attribution.children.first
520
- assert_equal "#{decode_char 8212} Famous Person", author.text.strip
521
- end
522
-
523
- test 'should parse credit line in markdown-style quote block like positional block attributes' do
524
- input = <<-EOS
525
- > I hold it that a little rebellion now and then is a good thing,
526
- > and as necessary in the political world as storms in the physical.
527
- -- Thomas Jefferson, https://jeffersonpapers.princeton.edu/selected-documents/james-madison-1[The Papers of Thomas Jefferson, Volume 11]
528
- EOS
529
-
530
- output = convert_string_to_embedded input
531
- assert_css '.quoteblock', output, 1
532
- assert_css '.quoteblock cite a[href="https://jeffersonpapers.princeton.edu/selected-documents/james-madison-1"]', output, 1
533
- end
534
-
535
- test 'quoted paragraph-style quote block with attribution' do
536
- input = <<-EOS
537
- "A famous quote.
538
- Some more inspiring words."
539
- -- Famous Person, Famous Source, Volume 1 (1999)
540
- EOS
541
- output = convert_string input
542
- assert_css '.quoteblock', output, 1
543
- assert_css '.quoteblock > blockquote', output, 1
544
- assert_xpath %(//*[@class = "quoteblock"]/blockquote[normalize-space(text()) = "A famous quote. Some more inspiring words."]), output, 1
545
- assert_css '.quoteblock > .attribution', output, 1
546
- assert_css '.quoteblock > .attribution > cite', output, 1
547
- assert_css '.quoteblock > .attribution > br + cite', output, 1
548
- assert_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]/cite[text() = "Famous Source, Volume 1 (1999)"]', output, 1
549
- attribution = xmlnodes_at_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]', output, 1
550
- author = attribution.children.first
551
- assert_equal "#{decode_char 8212} Famous Person", author.text.strip
552
- end
553
-
554
- test 'should parse credit line in quoted paragraph-style quote block like positional block attributes' do
555
- input = <<-EOS
556
- "I hold it that a little rebellion now and then is a good thing,
557
- and as necessary in the political world as storms in the physical."
558
- -- Thomas Jefferson, https://jeffersonpapers.princeton.edu/selected-documents/james-madison-1[The Papers of Thomas Jefferson, Volume 11]
559
- EOS
560
-
561
- output = convert_string_to_embedded input
562
- assert_css '.quoteblock', output, 1
563
- assert_css '.quoteblock cite a[href="https://jeffersonpapers.princeton.edu/selected-documents/james-madison-1"]', output, 1
564
- end
565
-
566
- test 'single-line verse block without attribution' do
567
- input = <<-EOS
568
- [verse]
569
- ____
570
- A famous verse.
571
- ____
572
- EOS
573
- output = convert_string input
574
- assert_css '.verseblock', output, 1
575
- assert_css '.verseblock > pre', output, 1
576
- assert_css '.verseblock > .attribution', output, 0
577
- assert_css '.verseblock p', output, 0
578
- assert_xpath '//*[@class = "verseblock"]/pre[normalize-space(text()) = "A famous verse."]', output, 1
579
- end
580
-
581
- test 'single-line verse block with attribution' do
582
- input = <<-EOS
583
- [verse, Famous Poet, Famous Poem]
584
- ____
585
- A famous verse.
586
- ____
587
- EOS
588
- output = convert_string input
589
- assert_css '.verseblock', output, 1
590
- assert_css '.verseblock p', output, 0
591
- assert_css '.verseblock > pre', output, 1
592
- assert_css '.verseblock > .attribution', output, 1
593
- assert_css '.verseblock > .attribution > cite', output, 1
594
- assert_css '.verseblock > .attribution > br + cite', output, 1
595
- assert_xpath '//*[@class = "verseblock"]/*[@class = "attribution"]/cite[text() = "Famous Poem"]', output, 1
596
- attribution = xmlnodes_at_xpath '//*[@class = "verseblock"]/*[@class = "attribution"]', output, 1
597
- author = attribution.children.first
598
- assert_equal "#{decode_char 8212} Famous Poet", author.text.strip
599
- end
600
-
601
- test 'single-line verse block with attribution converted to DocBook' do
602
- input = <<-EOS
603
- [verse, Famous Poet, Famous Poem]
604
- ____
605
- A famous verse.
606
- ____
607
- EOS
608
- output = convert_string input, :backend => :docbook
609
- assert_css 'blockquote', output, 1
610
- assert_css 'blockquote simpara', output, 0
611
- assert_css 'blockquote > literallayout', output, 1
612
- assert_css 'blockquote > attribution', output, 1
613
- assert_css 'blockquote > attribution > citetitle', output, 1
614
- assert_xpath '//blockquote/attribution/citetitle[text() = "Famous Poem"]', output, 1
615
- attribution = xmlnodes_at_xpath '//blockquote/attribution', output, 1
616
- author = attribution.children.first
617
- assert_equal 'Famous Poet', author.text.strip
618
- end
619
-
620
- test 'single-line epigraph verse block with attribution converted to DocBook' do
621
- input = <<-EOS
622
- [verse.epigraph, Famous Poet, Famous Poem]
623
- ____
624
- A famous verse.
625
- ____
626
- EOS
627
- output = convert_string input, :backend => :docbook
628
- assert_css 'epigraph', output, 1
629
- assert_css 'epigraph simpara', output, 0
630
- assert_css 'epigraph > literallayout', output, 1
631
- assert_css 'epigraph > attribution', output, 1
632
- assert_css 'epigraph > attribution > citetitle', output, 1
633
- assert_xpath '//epigraph/attribution/citetitle[text() = "Famous Poem"]', output, 1
634
- attribution = xmlnodes_at_xpath '//epigraph/attribution', output, 1
635
- author = attribution.children.first
636
- assert_equal 'Famous Poet', author.text.strip
637
- end
638
-
639
- test 'multi-stanza verse block' do
640
- input = <<-EOS
641
- [verse]
642
- ____
643
- A famous verse.
644
-
645
- Stanza two.
646
- ____
647
- EOS
648
- output = convert_string input
649
- assert_xpath '//*[@class = "verseblock"]', output, 1
650
- assert_xpath '//*[@class = "verseblock"]/pre', output, 1
651
- assert_xpath '//*[@class = "verseblock"]//p', output, 0
652
- assert_xpath '//*[@class = "verseblock"]/pre[contains(text(), "A famous verse.")]', output, 1
653
- assert_xpath '//*[@class = "verseblock"]/pre[contains(text(), "Stanza two.")]', output, 1
654
- end
655
-
656
- test 'verse block does not contain block elements' do
657
- input = <<-EOS
658
- [verse]
659
- ____
660
- A famous verse.
661
-
662
- ....
663
- not a literal
664
- ....
665
- ____
666
- EOS
667
- output = convert_string input
668
- assert_css '.verseblock', output, 1
669
- assert_css '.verseblock > pre', output, 1
670
- assert_css '.verseblock p', output, 0
671
- assert_css '.verseblock .literalblock', output, 0
672
- end
673
-
674
- test 'verse should have normal subs' do
675
- input = <<-EOS
676
- [verse]
677
- ____
678
- A famous verse
679
- ____
680
- EOS
681
-
682
- verse = block_from_string input
683
- assert_equal Asciidoctor::Substitutors::NORMAL_SUBS, verse.subs
684
- end
685
-
686
- test 'should not recognize callouts in a verse' do
687
- input = <<-EOS
688
- [verse]
689
- ____
690
- La la la <1>
691
- ____
692
- <1> Not pointing to a callout
693
- EOS
694
-
695
- output = convert_string_to_embedded input
696
- assert_xpath '//pre[text()="La la la <1>"]', output, 1
697
- assert_message @logger, :WARN, '<stdin>: line 5: no callout found for <1>', Hash
698
- end
699
-
700
- test 'should perform normal subs on a verse block' do
701
- input = <<-EOS
702
- [verse]
703
- ____
704
- _GET /groups/link:#group-id[\{group-id\}]_
705
- ____
706
- EOS
707
-
708
- output = convert_string_to_embedded input
709
- assert_includes output, '<pre class="content"><em>GET /groups/<a href="#group-id">{group-id}</a></em></pre>'
710
- end
711
- end
712
-
713
- context "Example Blocks" do
714
- test "can convert example block" do
715
- input = <<-EOS
716
- ====
717
- This is an example of an example block.
718
-
719
- How crazy is that?
720
- ====
721
- EOS
722
-
723
- output = convert_string input
724
- assert_xpath '//*[@class="exampleblock"]//p', output, 2
725
- end
726
-
727
- test 'assigns sequential numbered caption to example block with title' do
728
- input = <<-EOS
729
- .Writing Docs with AsciiDoc
730
- ====
731
- Here's how you write AsciiDoc.
732
-
733
- You just write.
734
- ====
735
-
736
- .Writing Docs with DocBook
737
- ====
738
- Here's how you write DocBook.
739
-
740
- You futz with XML.
741
- ====
742
- EOS
743
-
744
- doc = document_from_string input
745
- assert_equal 1, doc.blocks[0].numeral
746
- assert_equal 1, doc.blocks[0].number
747
- assert_equal 2, doc.blocks[1].numeral
748
- assert_equal 2, doc.blocks[1].number
749
- output = doc.convert
750
- assert_xpath '(//*[@class="exampleblock"])[1]/*[@class="title"][text()="Example 1. Writing Docs with AsciiDoc"]', output, 1
751
- assert_xpath '(//*[@class="exampleblock"])[2]/*[@class="title"][text()="Example 2. Writing Docs with DocBook"]', output, 1
752
- assert_equal 2, doc.attributes['example-number']
753
- end
754
-
755
- test 'assigns sequential character caption to example block with title' do
756
- input = <<-EOS
757
- :example-number: @
758
-
759
- .Writing Docs with AsciiDoc
760
- ====
761
- Here's how you write AsciiDoc.
762
-
763
- You just write.
764
- ====
765
-
766
- .Writing Docs with DocBook
767
- ====
768
- Here's how you write DocBook.
769
-
770
- You futz with XML.
771
- ====
772
- EOS
773
-
774
- doc = document_from_string input
775
- assert_equal 'A', doc.blocks[0].numeral
776
- assert_equal 'A', doc.blocks[0].number
777
- assert_equal 'B', doc.blocks[1].numeral
778
- assert_equal 'B', doc.blocks[1].number
779
- output = doc.convert
780
- assert_xpath '(//*[@class="exampleblock"])[1]/*[@class="title"][text()="Example A. Writing Docs with AsciiDoc"]', output, 1
781
- assert_xpath '(//*[@class="exampleblock"])[2]/*[@class="title"][text()="Example B. Writing Docs with DocBook"]', output, 1
782
- assert_equal 'B', doc.attributes['example-number']
783
- end
784
-
785
- test "explicit caption is used if provided" do
786
- input = <<-EOS
787
- [caption="Look! "]
788
- .Writing Docs with AsciiDoc
789
- ====
790
- Here's how you write AsciiDoc.
791
-
792
- You just write.
793
- ====
794
- EOS
795
-
796
- doc = document_from_string input
797
- assert_nil doc.blocks[0].numeral
798
- output = doc.convert
799
- assert_xpath '(//*[@class="exampleblock"])[1]/*[@class="title"][text()="Look! Writing Docs with AsciiDoc"]', output, 1
800
- refute doc.attributes.has_key?('example-number')
801
- end
802
-
803
- test 'automatic caption can be turned off and on and modified' do
804
- input = <<-EOS
805
- .first example
806
- ====
807
- an example
808
- ====
809
-
810
- :caption:
811
-
812
- .second example
813
- ====
814
- another example
815
- ====
816
-
817
- :caption!:
818
- :example-caption: Exhibit
819
-
820
- .third example
821
- ====
822
- yet another example
823
- ====
824
- EOS
825
-
826
- output = convert_string_to_embedded input
827
- assert_xpath '/*[@class="exampleblock"]', output, 3
828
- assert_xpath '(/*[@class="exampleblock"])[1]/*[@class="title"][starts-with(text(), "Example ")]', output, 1
829
- assert_xpath '(/*[@class="exampleblock"])[2]/*[@class="title"][text()="second example"]', output, 1
830
- assert_xpath '(/*[@class="exampleblock"])[3]/*[@class="title"][starts-with(text(), "Exhibit ")]', output, 1
831
- end
832
-
833
- test 'should warn if example block is not terminated' do
834
- input = <<-EOS
835
- outside
836
-
837
- ====
838
- inside
839
-
840
- still inside
841
-
842
- eof
843
- EOS
844
-
845
- output = convert_string_to_embedded input
846
- assert_xpath '/*[@class="exampleblock"]', output, 1
847
- assert_message @logger, :WARN, '<stdin>: line 3: unterminated example block', Hash
848
- end
849
- end
850
-
851
- context 'Admonition Blocks' do
852
- test 'caption block-level attribute should be used as caption' do
853
- input = <<-EOS
854
- :tip-caption: Pro Tip
855
-
856
- [caption="Pro Tip"]
857
- TIP: Override the caption of an admonition block using an attribute entry
858
- EOS
859
-
860
- output = convert_string_to_embedded input
861
- assert_xpath '/*[@class="admonitionblock tip"]//*[@class="icon"]/*[@class="title"][text()="Pro Tip"]', output, 1
862
- end
863
-
864
- test 'can override caption of admonition block using document attribute' do
865
- input = <<-EOS
866
- :tip-caption: Pro Tip
867
-
868
- TIP: Override the caption of an admonition block using an attribute entry
869
- EOS
870
-
871
- output = convert_string_to_embedded input
872
- assert_xpath '/*[@class="admonitionblock tip"]//*[@class="icon"]/*[@class="title"][text()="Pro Tip"]', output, 1
873
- end
874
-
875
- test 'blank caption document attribute should not blank admonition block caption' do
876
- input = <<-EOS
877
- :caption:
878
-
879
- TIP: Override the caption of an admonition block using an attribute entry
880
- EOS
881
-
882
- output = convert_string_to_embedded input
883
- assert_xpath '/*[@class="admonitionblock tip"]//*[@class="icon"]/*[@class="title"][text()="Tip"]', output, 1
884
- end
885
- end
886
-
887
- context "Preformatted Blocks" do
888
- test 'should separate adjacent paragraphs and listing into blocks' do
889
- input = <<-EOS
890
- paragraph 1
891
- ----
892
- listing content
893
- ----
894
- paragraph 2
895
- EOS
896
-
897
- output = convert_string_to_embedded input
898
- assert_xpath '/*[@class="paragraph"]/p', output, 2
899
- assert_xpath '/*[@class="listingblock"]', output, 1
900
- assert_xpath '(/*[@class="paragraph"]/following-sibling::*)[1][@class="listingblock"]', output, 1
901
- end
902
-
903
- test "should preserve endlines in literal block" do
904
- input = <<-EOS
905
- ....
906
- line one
907
-
908
- line two
909
-
910
- line three
911
- ....
912
- EOS
913
- [true, false].each {|header_footer|
914
- output = convert_string input, :header_footer => header_footer
915
- assert_xpath '//pre', output, 1
916
- assert_xpath '//pre/text()', output, 1
917
- text = xmlnodes_at_xpath('//pre/text()', output, 1).text
918
- lines = text.lines.entries
919
- assert_equal 5, lines.size
920
- expected = "line one\n\nline two\n\nline three".lines.entries
921
- assert_equal expected, lines
922
- blank_lines = output.scan(/\n[ \t]*\n/).size
923
- assert blank_lines >= 2
924
- }
925
- end
926
-
927
- test "should preserve endlines in listing block" do
928
- input = <<-EOS
929
- [source]
930
- ----
931
- line one
932
-
933
- line two
934
-
935
- line three
936
- ----
937
- EOS
938
- [true, false].each {|header_footer|
939
- output = convert_string input, header_footer => header_footer
940
- assert_xpath '//pre/code', output, 1
941
- assert_xpath '//pre/code/text()', output, 1
942
- text = xmlnodes_at_xpath('//pre/code/text()', output, 1).text
943
- lines = text.lines.entries
944
- assert_equal 5, lines.size
945
- expected = "line one\n\nline two\n\nline three".lines.entries
946
- assert_equal expected, lines
947
- blank_lines = output.scan(/\n[ \t]*\n/).size
948
- assert blank_lines >= 2
949
- }
950
- end
951
-
952
- test "should preserve endlines in verse block" do
953
- input = <<-EOS
954
- --
955
- [verse]
956
- ____
957
- line one
958
-
959
- line two
960
-
961
- line three
962
- ____
963
- --
964
- EOS
965
- [true, false].each {|header_footer|
966
- output = convert_string input, :header_footer => header_footer
967
- assert_xpath '//*[@class="verseblock"]/pre', output, 1
968
- assert_xpath '//*[@class="verseblock"]/pre/text()', output, 1
969
- text = xmlnodes_at_xpath('//*[@class="verseblock"]/pre/text()', output, 1).text
970
- lines = text.lines.entries
971
- assert_equal 5, lines.size
972
- expected = "line one\n\nline two\n\nline three".lines.entries
973
- assert_equal expected, lines
974
- blank_lines = output.scan(/\n[ \t]*\n/).size
975
- assert blank_lines >= 2
976
- }
977
- end
978
-
979
- test 'should strip leading and trailing blank lines when converting verbatim block' do
980
- input = <<-EOS
981
- [subs="attributes"]
982
- ....
983
-
984
-
985
- first line
986
-
987
- last line
988
-
989
- {empty}
990
-
991
- ....
992
- EOS
993
-
994
- doc = document_from_string input, :header_footer => false
995
- block = doc.blocks.first
996
- assert_equal ['', '', ' first line', '', 'last line', '', '{empty}', ''], block.lines
997
- result = doc.convert
998
- assert_xpath %(//pre[text()=" first line\n\nlast line"]), result, 1
999
- end
1000
-
1001
- test 'should process block with CRLF endlines' do
1002
- input = <<-EOS
1003
- [source]\r
1004
- ----\r
1005
- source line 1\r
1006
- source line 2\r
1007
- ----\r
1008
- EOS
1009
-
1010
- output = convert_string_to_embedded input
1011
- refute_match(/\[source\]/, output)
1012
- assert_xpath '/*[@class="listingblock"]//pre', output, 1
1013
- assert_xpath '/*[@class="listingblock"]//pre/code', output, 1
1014
- assert_xpath %(/*[@class="listingblock"]//pre/code[text()="source line 1\nsource line 2"]), output, 1
1015
- end
1016
-
1017
- test 'should remove block indent if indent attribute is 0' do
1018
- input = <<-EOS
1019
- [indent="0"]
1020
- ----
1021
- def names
1022
-
1023
- @names.split
1024
-
1025
- end
1026
- ----
1027
- EOS
1028
-
1029
- expected = <<-EOS
1030
- def names
1031
-
1032
- @names.split
1033
-
1034
- end
1035
- EOS
1036
-
1037
- output = convert_string_to_embedded input
1038
- assert_css 'pre', output, 1
1039
- assert_css '.listingblock pre', output, 1
1040
- result = xmlnodes_at_xpath('//pre', output, 1).text
1041
- assert_equal expected.chomp, result
1042
- end
1043
-
1044
- test 'should not remove block indent if indent attribute is -1' do
1045
- input = <<-EOS
1046
- [indent="-1"]
1047
- ----
1048
- def names
1049
-
1050
- @names.split
1051
-
1052
- end
1053
- ----
1054
- EOS
1055
-
1056
- expected = <<-EOS
1057
- def names
1058
-
1059
- @names.split
1060
-
1061
- end
1062
- EOS
1063
-
1064
- output = convert_string_to_embedded input
1065
- assert_css 'pre', output, 1
1066
- assert_css '.listingblock pre', output, 1
1067
- result = xmlnodes_at_xpath('//pre', output, 1).text
1068
- assert_equal expected.chomp, result
1069
- end
1070
-
1071
- test 'should set block indent to value specified by indent attribute' do
1072
- input = <<-EOS
1073
- [indent="1"]
1074
- ----
1075
- def names
1076
-
1077
- @names.split
1078
-
1079
- end
1080
- ----
1081
- EOS
1082
-
1083
- expected = <<-EOS
1084
- def names
1085
-
1086
- @names.split
1087
-
1088
- end
1089
- EOS
1090
-
1091
- output = convert_string_to_embedded input
1092
- assert_css 'pre', output, 1
1093
- assert_css '.listingblock pre', output, 1
1094
- result = xmlnodes_at_xpath('//pre', output, 1).text
1095
- assert_equal expected.chomp, result
1096
- end
1097
-
1098
- test 'should set block indent to value specified by indent document attribute' do
1099
- input = <<-EOS
1100
- :source-indent: 1
1101
-
1102
- [source,ruby]
1103
- ----
1104
- def names
1105
-
1106
- @names.split
1107
-
1108
- end
1109
- ----
1110
- EOS
1111
-
1112
- expected = <<-EOS
1113
- def names
1114
-
1115
- @names.split
1116
-
1117
- end
1118
- EOS
1119
-
1120
- output = convert_string_to_embedded input
1121
- assert_css 'pre', output, 1
1122
- assert_css '.listingblock pre', output, 1
1123
- result = xmlnodes_at_xpath('//pre', output, 1).text
1124
- assert_equal expected.chomp, result
1125
- end
1126
-
1127
- test 'should expand tabs if tabsize attribute is positive' do
1128
- input = <<-EOS
1129
- :tabsize: 4
1130
-
1131
- [indent=0]
1132
- ----
1133
- def names
1134
-
1135
- @names.split
1136
-
1137
- end
1138
- ----
1139
- EOS
1140
-
1141
- expected = <<-EOS
1142
- def names
1143
-
1144
- @names.split
1145
-
1146
- end
1147
- EOS
1148
-
1149
- output = convert_string_to_embedded input
1150
- assert_css 'pre', output, 1
1151
- assert_css '.listingblock pre', output, 1
1152
- result = xmlnodes_at_xpath('//pre', output, 1).text
1153
- assert_equal expected.chomp, result
1154
- end
1155
-
1156
- test 'literal block should honor nowrap option' do
1157
- input = <<-EOS
1158
- [options="nowrap"]
1159
- ----
1160
- Do not wrap me if I get too long.
1161
- ----
1162
- EOS
1163
-
1164
- output = convert_string_to_embedded input
1165
- assert_css 'pre.nowrap', output, 1
1166
- end
1167
-
1168
- test 'literal block should set nowrap class if prewrap document attribute is disabled' do
1169
- input = <<-EOS
1170
- :prewrap!:
1171
-
1172
- ----
1173
- Do not wrap me if I get too long.
1174
- ----
1175
- EOS
1176
-
1177
- output = convert_string_to_embedded input
1178
- assert_css 'pre.nowrap', output, 1
1179
- end
1180
-
1181
- test 'literal block should honor explicit subs list' do
1182
- input = <<-EOS
1183
- [subs="verbatim,quotes"]
1184
- ----
1185
- Map<String, String> *attributes*; //<1>
1186
- ----
1187
- EOS
1188
-
1189
- block = block_from_string input
1190
- assert_equal [:specialcharacters,:callouts,:quotes], block.subs
1191
- output = block.convert
1192
- assert_includes output, 'Map&lt;String, String&gt; <strong>attributes</strong>;'
1193
- assert_xpath '//pre/b[text()="(1)"]', output, 1
1194
- end
1195
-
1196
- test 'should be able to disable callouts for literal block' do
1197
- input = <<-EOS
1198
- [subs="specialcharacters"]
1199
- ----
1200
- No callout here <1>
1201
- ----
1202
- EOS
1203
- block = block_from_string input
1204
- assert_equal [:specialcharacters], block.subs
1205
- output = block.convert
1206
- assert_xpath '//pre/b[text()="(1)"]', output, 0
1207
- end
1208
-
1209
- test 'listing block should honor explicit subs list' do
1210
- input = <<-EOS
1211
- [subs="specialcharacters,quotes"]
1212
- ----
1213
- $ *python functional_tests.py*
1214
- Traceback (most recent call last):
1215
- File "functional_tests.py", line 4, in <module>
1216
- assert 'Django' in browser.title
1217
- AssertionError
1218
- ----
1219
- EOS
1220
-
1221
- output = convert_string_to_embedded input
1222
-
1223
- assert_css '.listingblock pre', output, 1
1224
- assert_css '.listingblock pre strong', output, 1
1225
- assert_css '.listingblock pre em', output, 0
1226
-
1227
- input2 = <<-EOS
1228
- [subs="specialcharacters,macros"]
1229
- ----
1230
- $ pass:quotes[*python functional_tests.py*]
1231
- Traceback (most recent call last):
1232
- File "functional_tests.py", line 4, in <module>
1233
- assert pass:quotes['Django'] in browser.title
1234
- AssertionError
1235
- ----
1236
- EOS
1237
-
1238
- output2 = convert_string_to_embedded input2
1239
- # FIXME JRuby is adding extra trailing endlines in the second document,
1240
- # for now, rstrip is necessary
1241
- assert_equal output.rstrip, output2.rstrip
1242
- end
1243
-
1244
- test 'first character of block title may be a period if not followed by space' do
1245
- input = <<-EOS
1246
- ..gitignore
1247
- ----
1248
- /.bundle/
1249
- /build/
1250
- /Gemfile.lock
1251
- ----
1252
- EOS
1253
-
1254
- output = convert_string_to_embedded input
1255
- assert_xpath '//*[@class="title"][text()=".gitignore"]', output
1256
- end
1257
-
1258
- test 'listing block without title should generate screen element in docbook' do
1259
- input = <<-EOS
1260
- ----
1261
- listing block
1262
- ----
1263
- EOS
1264
-
1265
- output = convert_string_to_embedded input, :backend => 'docbook'
1266
- assert_xpath '/screen[text()="listing block"]', output, 1
1267
- end
1268
-
1269
- test 'listing block with title should generate screen element inside formalpara element in docbook' do
1270
- input = <<-EOS
1271
- .title
1272
- ----
1273
- listing block
1274
- ----
1275
- EOS
1276
-
1277
- output = convert_string_to_embedded input, :backend => 'docbook'
1278
- assert_xpath '/formalpara', output, 1
1279
- assert_xpath '/formalpara/title[text()="title"]', output, 1
1280
- assert_xpath '/formalpara/para/screen[text()="listing block"]', output, 1
1281
- end
1282
-
1283
- test 'source block with no title or language should generate screen element in docbook' do
1284
- input = <<-EOS
1285
- [source]
1286
- ----
1287
- listing block
1288
- ----
1289
- EOS
1290
-
1291
- output = convert_string_to_embedded input, :backend => 'docbook'
1292
- assert_xpath '/screen[text()="listing block"]', output, 1
1293
- end
1294
-
1295
- test 'source block with title and no language should generate screen element inside formalpara element in docbook' do
1296
- input = <<-EOS
1297
- [source]
1298
- .title
1299
- ----
1300
- listing block
1301
- ----
1302
- EOS
1303
-
1304
- output = convert_string_to_embedded input, :backend => 'docbook'
1305
- assert_xpath '/formalpara', output, 1
1306
- assert_xpath '/formalpara/title[text()="title"]', output, 1
1307
- assert_xpath '/formalpara/para/screen[text()="listing block"]', output, 1
1308
- end
1309
- end
1310
-
1311
- context "Open Blocks" do
1312
- test "can convert open block" do
1313
- input = <<-EOS
1314
- --
1315
- This is an open block.
1316
-
1317
- It can span multiple lines.
1318
- --
1319
- EOS
1320
-
1321
- output = convert_string input
1322
- assert_xpath '//*[@class="openblock"]//p', output, 2
1323
- end
1324
-
1325
- test "open block can contain another block" do
1326
- input = <<-EOS
1327
- --
1328
- This is an open block.
1329
-
1330
- It can span multiple lines.
1331
-
1332
- ____
1333
- It can hold great quotes like this one.
1334
- ____
1335
- --
1336
- EOS
1337
-
1338
- output = convert_string input
1339
- assert_xpath '//*[@class="openblock"]//p', output, 3
1340
- assert_xpath '//*[@class="openblock"]//*[@class="quoteblock"]', output, 1
1341
- end
1342
-
1343
- test 'should transfer id and reftext on open block to DocBook output' do
1344
- input = <<-EOS
1345
- Check out that <<open>>!
1346
-
1347
- [[open,Open Block]]
1348
- --
1349
- This is an open block.
1350
-
1351
- TIP: An open block can have other blocks inside of it.
1352
- --
1353
-
1354
- Back to our regularly scheduled programming.
1355
- EOS
1356
-
1357
- output = convert_string input, :backend => :docbook, :keep_namespaces => true
1358
- assert_css 'article > simpara', output, 2
1359
- assert_css 'article > para', output, 1
1360
- assert_css 'article > para > simpara', output, 1
1361
- assert_css 'article > para > tip', output, 1
1362
- open = xmlnodes_at_xpath '/xmlns:article/xmlns:para', output, 1
1363
- # nokogiri can't make up its mind
1364
- id = open.attribute('id') || open.attribute('xml:id')
1365
- refute_nil id
1366
- assert_equal 'open', id.value
1367
- xreflabel = open.attribute('xreflabel')
1368
- refute_nil xreflabel
1369
- assert_equal 'Open Block', xreflabel.value
1370
- end
1371
-
1372
- test 'should transfer id and reftext on open paragraph to DocBook output' do
1373
- input = <<-EOS
1374
- [open#openpara,reftext="Open Paragraph"]
1375
- This is an open paragraph.
1376
- EOS
1377
-
1378
- output = convert_string input, :backend => :docbook, :keep_namespaces => true
1379
- assert_css 'article > simpara', output, 1
1380
- open = xmlnodes_at_xpath '/xmlns:article/xmlns:simpara', output, 1
1381
- open = xmlnodes_at_xpath '/xmlns:article/xmlns:simpara[text()="This is an open paragraph."]', output, 1
1382
- # nokogiri can't make up its mind
1383
- id = open.attribute('id') || open.attribute('xml:id')
1384
- refute_nil id
1385
- assert_equal 'openpara', id.value
1386
- xreflabel = open.attribute('xreflabel')
1387
- refute_nil xreflabel
1388
- assert_equal 'Open Paragraph', xreflabel.value
1389
- end
1390
-
1391
- test 'should transfer title on open block to DocBook output' do
1392
- input = <<-EOS
1393
- .Behold the open
1394
- --
1395
- This is an open block with a title.
1396
- --
1397
- EOS
1398
-
1399
- output = convert_string input, :backend => :docbook
1400
- assert_css 'article > formalpara', output, 1
1401
- assert_css 'article > formalpara > *', output, 2
1402
- assert_css 'article > formalpara > title', output, 1
1403
- assert_xpath '/article/formalpara/title[text()="Behold the open"]', output, 1
1404
- assert_css 'article > formalpara > para', output, 1
1405
- assert_css 'article > formalpara > para > simpara', output, 1
1406
- end
1407
-
1408
- test 'should transfer title on open paragraph to DocBook output' do
1409
- input = <<-EOS
1410
- .Behold the open
1411
- This is an open paragraph with a title.
1412
- EOS
1413
-
1414
- output = convert_string input, :backend => :docbook
1415
- assert_css 'article > formalpara', output, 1
1416
- assert_css 'article > formalpara > *', output, 2
1417
- assert_css 'article > formalpara > title', output, 1
1418
- assert_xpath '/article/formalpara/title[text()="Behold the open"]', output, 1
1419
- assert_css 'article > formalpara > para', output, 1
1420
- assert_css 'article > formalpara > para[text()="This is an open paragraph with a title."]', output, 1
1421
- end
1422
-
1423
- test 'should transfer role on open block to DocBook output' do
1424
- input = <<-EOS
1425
- [.container]
1426
- --
1427
- This is an open block.
1428
- It holds stuff.
1429
- --
1430
- EOS
1431
-
1432
- output = convert_string input, :backend => :docbook
1433
- assert_css 'article > para[role=container]', output, 1
1434
- assert_css 'article > para[role=container] > simpara', output, 1
1435
- end
1436
-
1437
- test 'should transfer role on open paragraph to DocBook output' do
1438
- input = <<-EOS
1439
- [.container]
1440
- This is an open block.
1441
- It holds stuff.
1442
- EOS
1443
-
1444
- output = convert_string input, :backend => :docbook
1445
- assert_css 'article > simpara[role=container]', output, 1
1446
- end
1447
- end
1448
-
1449
- context 'Passthrough Blocks' do
1450
- test 'can parse a passthrough block' do
1451
- input = <<-EOS
1452
- ++++
1453
- This is a passthrough block.
1454
- ++++
1455
- EOS
1456
-
1457
- block = block_from_string input
1458
- refute_nil block
1459
- assert_equal 1, block.lines.size
1460
- assert_equal 'This is a passthrough block.', block.source
1461
- end
1462
-
1463
- test 'does not perform subs on a passthrough block by default' do
1464
- input = <<-EOS
1465
- :type: passthrough
1466
-
1467
- ++++
1468
- This is a '{type}' block.
1469
- http://asciidoc.org
1470
- image:tiger.png[]
1471
- ++++
1472
- EOS
1473
-
1474
- expected = %(This is a '{type}' block.\nhttp://asciidoc.org\nimage:tiger.png[])
1475
- output = convert_string_to_embedded input
1476
- assert_equal expected, output.strip
1477
- end
1478
-
1479
- test 'does not perform subs on a passthrough block with pass style by default' do
1480
- input = <<-EOS
1481
- :type: passthrough
1482
-
1483
- [pass]
1484
- ++++
1485
- This is a '{type}' block.
1486
- http://asciidoc.org
1487
- image:tiger.png[]
1488
- ++++
1489
- EOS
1490
-
1491
- expected = %(This is a '{type}' block.\nhttp://asciidoc.org\nimage:tiger.png[])
1492
- output = convert_string_to_embedded input
1493
- assert_equal expected, output.strip
1494
- end
1495
-
1496
- test 'passthrough block honors explicit subs list' do
1497
- input = <<-EOS
1498
- :type: passthrough
1499
-
1500
- [subs="attributes,quotes,macros"]
1501
- ++++
1502
- This is a _{type}_ block.
1503
- http://asciidoc.org
1504
- ++++
1505
- EOS
1506
-
1507
- expected = %(This is a <em>passthrough</em> block.\n<a href="http://asciidoc.org" class="bare">http://asciidoc.org</a>)
1508
- output = convert_string_to_embedded input
1509
- assert_equal expected, output.strip
1510
- end
1511
-
1512
- test 'should strip leading and trailing blank lines when converting raw block' do
1513
- input = <<-EOS
1514
- ++++
1515
- line above
1516
- ++++
1517
-
1518
- ++++
1519
-
1520
-
1521
- first line
1522
-
1523
- last line
1524
-
1525
-
1526
- ++++
1527
-
1528
- ++++
1529
- line below
1530
- ++++
1531
- EOS
1532
-
1533
- doc = document_from_string input, :header_footer => false
1534
- block = doc.blocks[1]
1535
- assert_equal ['', '', ' first line', '', 'last line', '', ''], block.lines
1536
- result = doc.convert
1537
- assert_equal "line above\n first line\n\nlast line\nline below", result, 1
1538
- end
1539
- end
1540
-
1541
- context 'Math blocks' do
1542
- test 'should add LaTeX math delimiters around latexmath block content' do
1543
- input = <<-'EOS'
1544
- [latexmath]
1545
- ++++
1546
- \sqrt{3x-1}+(1+x)^2 < y
1547
- ++++
1548
- EOS
1549
-
1550
- output = convert_string_to_embedded input
1551
- assert_css '.stemblock', output, 1
1552
- nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
1553
- assert_equal '\[\sqrt{3x-1}+(1+x)^2 &lt; y\]', nodes.first.to_s.strip
1554
- end
1555
-
1556
- test 'should not add LaTeX math delimiters around latexmath block content if already present' do
1557
- input = <<-'EOS'
1558
- [latexmath]
1559
- ++++
1560
- \[\sqrt{3x-1}+(1+x)^2 < y\]
1561
- ++++
1562
- EOS
1563
-
1564
- output = convert_string_to_embedded input
1565
- assert_css '.stemblock', output, 1
1566
- nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
1567
- assert_equal '\[\sqrt{3x-1}+(1+x)^2 &lt; y\]', nodes.first.to_s.strip
1568
- end
1569
-
1570
- test 'should display latexmath block in alt of equation in DocBook backend' do
1571
- input = <<-'EOS'
1572
- [latexmath]
1573
- ++++
1574
- \sqrt{3x-1}+(1+x)^2 < y
1575
- ++++
1576
- EOS
1577
-
1578
- expect = <<-'EOS'
1579
- <informalequation>
1580
- <alt><![CDATA[\sqrt{3x-1}+(1+x)^2 < y]]></alt>
1581
- <mathphrase><![CDATA[\sqrt{3x-1}+(1+x)^2 < y]]></mathphrase>
1582
- </informalequation>
1583
- EOS
1584
-
1585
- output = convert_string_to_embedded input, :backend => :docbook
1586
- assert_equal expect.strip, output.strip
1587
- end
1588
-
1589
- test 'should not split equation in AsciiMath block at single newline' do
1590
- input = <<-'EOS'
1591
- [asciimath]
1592
- ++++
1593
- f: bbb"N" -> bbb"N"
1594
- f: x |-> x + 1
1595
- ++++
1596
- EOS
1597
- expected = <<-'EOS'.chomp
1598
- \$f: bbb"N" -&gt; bbb"N"
1599
- f: x |-&gt; x + 1\$
1600
- EOS
1601
-
1602
- output = convert_string_to_embedded input
1603
- assert_css '.stemblock', output, 1
1604
- nodes = xmlnodes_at_xpath '//*[@class="content"]', output
1605
- assert_equal expected, nodes.first.inner_html.strip
1606
- end
1607
-
1608
- test 'should split equation in AsciiMath block at escaped newline' do
1609
- input = <<-'EOS'
1610
- [asciimath]
1611
- ++++
1612
- f: bbb"N" -> bbb"N" \
1613
- f: x |-> x + 1
1614
- ++++
1615
- EOS
1616
- expected = <<-'EOS'.chomp
1617
- \$f: bbb"N" -&gt; bbb"N"\$<br>
1618
- \$f: x |-&gt; x + 1\$
1619
- EOS
1620
-
1621
- output = convert_string_to_embedded input
1622
- assert_css '.stemblock', output, 1
1623
- nodes = xmlnodes_at_xpath '//*[@class="content"]', output
1624
- assert_equal expected, nodes.first.inner_html.strip
1625
- end
1626
-
1627
- test 'should split equation in AsciiMath block at sequence of escaped newlines' do
1628
- input = <<-'EOS'
1629
- [asciimath]
1630
- ++++
1631
- f: bbb"N" -> bbb"N" \
1632
- \
1633
- f: x |-> x + 1
1634
- ++++
1635
- EOS
1636
- expected = <<-'EOS'.chomp
1637
- \$f: bbb"N" -&gt; bbb"N"\$<br>
1638
- <br>
1639
- \$f: x |-&gt; x + 1\$
1640
- EOS
1641
-
1642
- output = convert_string_to_embedded input
1643
- assert_css '.stemblock', output, 1
1644
- nodes = xmlnodes_at_xpath '//*[@class="content"]', output
1645
- assert_equal expected, nodes.first.inner_html.strip
1646
- end
1647
-
1648
- test 'should split equation in AsciiMath block at newline sequence and preserve breaks' do
1649
- input = <<-'EOS'
1650
- [asciimath]
1651
- ++++
1652
- f: bbb"N" -> bbb"N"
1653
-
1654
-
1655
- f: x |-> x + 1
1656
- ++++
1657
- EOS
1658
- expected = <<-'EOS'.chomp
1659
- \$f: bbb"N" -&gt; bbb"N"\$<br>
1660
- <br>
1661
- <br>
1662
- \$f: x |-&gt; x + 1\$
1663
- EOS
1664
-
1665
- output = convert_string_to_embedded input
1666
- assert_css '.stemblock', output, 1
1667
- nodes = xmlnodes_at_xpath '//*[@class="content"]', output
1668
- assert_equal expected, nodes.first.inner_html.strip
1669
- end
1670
-
1671
- test 'should add AsciiMath delimiters around asciimath block content' do
1672
- input = <<-'EOS'
1673
- [asciimath]
1674
- ++++
1675
- sqrt(3x-1)+(1+x)^2 < y
1676
- ++++
1677
- EOS
1678
-
1679
- output = convert_string_to_embedded input
1680
- assert_css '.stemblock', output, 1
1681
- nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
1682
- assert_equal '\$sqrt(3x-1)+(1+x)^2 &lt; y\$', nodes.first.to_s.strip
1683
- end
1684
-
1685
- test 'should not add AsciiMath delimiters around asciimath block content if already present' do
1686
- input = <<-'EOS'
1687
- [asciimath]
1688
- ++++
1689
- \$sqrt(3x-1)+(1+x)^2 < y\$
1690
- ++++
1691
- EOS
1692
-
1693
- output = convert_string_to_embedded input
1694
- assert_css '.stemblock', output, 1
1695
- nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
1696
- assert_equal '\$sqrt(3x-1)+(1+x)^2 &lt; y\$', nodes.first.to_s.strip
1697
- end
1698
-
1699
- test 'should convert contents of asciimath block to MathML in DocBook output if asciimath gem is available' do
1700
- asciimath_available = !(Asciidoctor::Helpers.require_library 'asciimath', true, :ignore).nil?
1701
- input = <<-'EOS'
1702
- [asciimath]
1703
- ++++
1704
- x+b/(2a)<+-sqrt((b^2)/(4a^2)-c/a)
1705
- ++++
1706
- EOS
1707
-
1708
- expect = %(<informalequation>
1709
- <mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mfrac><mml:mi>b</mml:mi><mml:mrow><mml:mn>2</mml:mn><mml:mi>a</mml:mi></mml:mrow></mml:mfrac><mml:mo>&#x003C;</mml:mo><mml:mo>&#x00B1;</mml:mo><mml:msqrt><mml:mrow><mml:mfrac><mml:msup><mml:mi>b</mml:mi><mml:mn>2</mml:mn></mml:msup><mml:mrow><mml:mn>4</mml:mn><mml:msup><mml:mi>a</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:mfrac><mml:mo>&#x2212;</mml:mo><mml:mfrac><mml:mi>c</mml:mi><mml:mi>a</mml:mi></mml:mfrac></mml:mrow></mml:msqrt></mml:math>
1710
- </informalequation>)
1711
-
1712
- using_memory_logger do |logger|
1713
- doc = document_from_string input, :backend => :docbook, :header_footer => false
1714
- actual = doc.convert
1715
- if asciimath_available
1716
- assert_equal expect.strip, actual.strip
1717
- assert_equal :loaded, doc.converter.instance_variable_get(:@asciimath)
1718
- else
1719
- assert_message logger, :WARN, 'optional gem \'asciimath\' is not installed. Functionality disabled.'
1720
- assert_equal :unavailable, doc.converter.instance_variable_get(:@asciimath)
1721
- end
1722
- end
1723
- end
1724
-
1725
- test 'should output title for latexmath block if defined' do
1726
- input = <<-'EOS'
1727
- .The Lorenz Equations
1728
- [latexmath]
1729
- ++++
1730
- \begin{aligned}
1731
- \dot{x} & = \sigma(y-x) \\
1732
- \dot{y} & = \rho x - y - xz \\
1733
- \dot{z} & = -\beta z + xy
1734
- \end{aligned}
1735
- ++++
1736
- EOS
1737
-
1738
- output = convert_string_to_embedded input
1739
- assert_css '.stemblock', output, 1
1740
- assert_css '.stemblock .title', output, 1
1741
- assert_xpath '//*[@class="title"][text()="The Lorenz Equations"]', output, 1
1742
- end
1743
-
1744
- test 'should output title for asciimath block if defined' do
1745
- input = <<-'EOS'
1746
- .Simple fraction
1747
- [asciimath]
1748
- ++++
1749
- a//b
1750
- ++++
1751
- EOS
1752
-
1753
- output = convert_string_to_embedded input
1754
- assert_css '.stemblock', output, 1
1755
- assert_css '.stemblock .title', output, 1
1756
- assert_xpath '//*[@class="title"][text()="Simple fraction"]', output, 1
1757
- end
1758
-
1759
- test 'should add AsciiMath delimiters around stem block content if stem attribute is asciimath, empty, or not set' do
1760
- input = <<-'EOS'
1761
- [stem]
1762
- ++++
1763
- sqrt(3x-1)+(1+x)^2 < y
1764
- ++++
1765
- EOS
1766
-
1767
- [
1768
- {},
1769
- {'stem' => ''},
1770
- {'stem' => 'asciimath'},
1771
- {'stem' => 'bogus'}
1772
- ].each do |attributes|
1773
- output = convert_string_to_embedded input, :attributes => attributes
1774
- assert_css '.stemblock', output, 1
1775
- nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
1776
- assert_equal '\$sqrt(3x-1)+(1+x)^2 &lt; y\$', nodes.first.to_s.strip
1777
- end
1778
- end
1779
-
1780
- test 'should add LaTeX math delimiters around stem block content if stem attribute is latexmath, latex, or tex' do
1781
- input = <<-'EOS'
1782
- [stem]
1783
- ++++
1784
- \sqrt{3x-1}+(1+x)^2 < y
1785
- ++++
1786
- EOS
1787
-
1788
- [
1789
- {'stem' => 'latexmath'},
1790
- {'stem' => 'latex'},
1791
- {'stem' => 'tex'}
1792
- ].each do |attributes|
1793
- output = convert_string_to_embedded input, :attributes => attributes
1794
- assert_css '.stemblock', output, 1
1795
- nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
1796
- assert_equal '\[\sqrt{3x-1}+(1+x)^2 &lt; y\]', nodes.first.to_s.strip
1797
- end
1798
- end
1799
-
1800
- test 'should allow stem style to be set using second positional argument of block attributes' do
1801
- input = <<-EOS
1802
- :stem: latexmath
1803
-
1804
- [stem,asciimath]
1805
- ++++
1806
- sqrt(3x-1)+(1+x)^2 < y
1807
- ++++
1808
- EOS
1809
-
1810
- doc = document_from_string input
1811
- stemblock = doc.blocks[0]
1812
- assert_equal :stem, stemblock.context
1813
- assert_equal 'asciimath', stemblock.attributes['style']
1814
- output = doc.convert :header_footer => false
1815
- assert_css '.stemblock', output, 1
1816
- nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
1817
- assert_equal '\$sqrt(3x-1)+(1+x)^2 &lt; y\$', nodes.first.to_s.strip
1818
- end
1819
- end
1820
-
1821
- context 'Metadata' do
1822
- test 'block title above section gets carried over to first block in section' do
1823
- input = <<-EOS
1824
- .Title
1825
- == Section
1826
-
1827
- paragraph
1828
- EOS
1829
- output = convert_string input
1830
- assert_xpath '//*[@class="paragraph"]', output, 1
1831
- assert_xpath '//*[@class="paragraph"]/*[@class="title"][text() = "Title"]', output, 1
1832
- assert_xpath '//*[@class="paragraph"]/p[text() = "paragraph"]', output, 1
1833
- end
1834
-
1835
- test 'block title above document title demotes document title to a section title' do
1836
- input = <<-EOS
1837
- .Block title
1838
- = Section Title
1839
-
1840
- section paragraph
1841
- EOS
1842
- output = convert_string input
1843
- assert_xpath '//*[@id="header"]/*', output, 0
1844
- assert_xpath '//*[@id="preamble"]/*', output, 0
1845
- assert_xpath '//*[@id="content"]/h1[text()="Section Title"]', output, 1
1846
- assert_xpath '//*[@class="paragraph"]', output, 1
1847
- assert_xpath '//*[@class="paragraph"]/*[@class="title"][text()="Block title"]', output, 1
1848
- assert_message @logger, :ERROR, '<stdin>: line 2: level 0 sections can only be used when doctype is book', Hash
1849
- end
1850
-
1851
- test 'block title above document title gets carried over to first block in first section if no preamble' do
1852
- input = <<-EOS
1853
- :doctype: book
1854
- .Block title
1855
- = Document Title
1856
-
1857
- == First Section
1858
-
1859
- paragraph
1860
- EOS
1861
- doc = document_from_string input
1862
- # NOTE block title demotes document title to level-0 section
1863
- refute doc.header?
1864
- output = doc.convert
1865
- assert_xpath '//*[@class="sect1"]//*[@class="paragraph"]/*[@class="title"][text() = "Block title"]', output, 1
1866
- end
1867
-
1868
- test 'empty attribute list should not appear in output' do
1869
- input = <<-EOS
1870
- []
1871
- --
1872
- Block content
1873
- --
1874
- EOS
1875
-
1876
- output = convert_string_to_embedded input
1877
- assert_includes output, 'Block content'
1878
- refute_includes output, '[]'
1879
- end
1880
-
1881
- test 'empty block anchor should not appear in output' do
1882
- input = <<-EOS
1883
- [[]]
1884
- --
1885
- Block content
1886
- --
1887
- EOS
1888
-
1889
- output = convert_string_to_embedded input
1890
- assert_includes output, 'Block content'
1891
- refute_includes output, '[[]]'
1892
- end
1893
- end
1894
-
1895
- context 'Images' do
1896
- test 'can convert block image with alt text defined in macro' do
1897
- input = <<-EOS
1898
- image::images/tiger.png[Tiger]
1899
- EOS
1900
-
1901
- output = convert_string_to_embedded input
1902
- assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
1903
- end
1904
-
1905
- test 'converts SVG image using img element by default' do
1906
- input = <<-EOS
1907
- image::tiger.svg[Tiger]
1908
- EOS
1909
-
1910
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SERVER
1911
- assert_xpath '/*[@class="imageblock"]//img[@src="tiger.svg"][@alt="Tiger"]', output, 1
1912
- end
1913
-
1914
- test 'converts interactive SVG image with alt text using object element' do
1915
- input = <<-EOS
1916
- :imagesdir: images
1917
-
1918
- [%interactive]
1919
- image::tiger.svg[Tiger,100]
1920
- EOS
1921
-
1922
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SERVER
1923
- assert_xpath '/*[@class="imageblock"]//object[@type="image/svg+xml"][@data="images/tiger.svg"][@width="100"]/span[@class="alt"][text()="Tiger"]', output, 1
1924
- end
1925
-
1926
- test 'converts SVG image with alt text using img element when safe mode is secure' do
1927
- input = <<-EOS
1928
- [%interactive]
1929
- image::images/tiger.svg[Tiger,100]
1930
- EOS
1931
-
1932
- output = convert_string_to_embedded input
1933
- assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.svg"][@alt="Tiger"]', output, 1
1934
- end
1935
-
1936
- test 'inserts fallback image for SVG inside object element using same dimensions' do
1937
- input = <<-EOS
1938
- :imagesdir: images
1939
-
1940
- [%interactive]
1941
- image::tiger.svg[Tiger,100,fallback=tiger.png]
1942
- EOS
1943
-
1944
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SERVER
1945
- assert_xpath '/*[@class="imageblock"]//object[@type="image/svg+xml"][@data="images/tiger.svg"][@width="100"]/img[@src="images/tiger.png"][@width="100"]', output, 1
1946
- end
1947
-
1948
- test 'detects SVG image URI that contains a query string' do
1949
- input = <<-EOS
1950
- :imagesdir: images
1951
-
1952
- [%interactive]
1953
- image::http://example.org/tiger.svg?foo=bar[Tiger,100]
1954
- EOS
1955
-
1956
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SERVER
1957
- assert_xpath '/*[@class="imageblock"]//object[@type="image/svg+xml"][@data="http://example.org/tiger.svg?foo=bar"][@width="100"]/span[@class="alt"][text()="Tiger"]', output, 1
1958
- end
1959
-
1960
- test 'detects SVG image when format attribute is svg' do
1961
- input = <<-EOS
1962
- :imagesdir: images
1963
-
1964
- [%interactive]
1965
- image::http://example.org/tiger-svg[Tiger,100,format=svg]
1966
- EOS
1967
-
1968
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SERVER
1969
- assert_xpath '/*[@class="imageblock"]//object[@type="image/svg+xml"][@data="http://example.org/tiger-svg"][@width="100"]/span[@class="alt"][text()="Tiger"]', output, 1
1970
- end
1971
-
1972
- test 'converts inline SVG image using svg element' do
1973
- input = <<-EOS
1974
- :imagesdir: fixtures
1975
-
1976
- [%inline]
1977
- image::circle.svg[Tiger,100]
1978
- EOS
1979
-
1980
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'docdir' => testdir }
1981
- assert_match(/<svg\s[^>]*width="100px"[^>]*>/, output, 1)
1982
- refute_match(/<svg\s[^>]*width="500px"[^>]*>/, output)
1983
- refute_match(/<svg\s[^>]*height="500px"[^>]*>/, output)
1984
- refute_match(/<svg\s[^>]*style="width:500px;height:500px"[^>]*>/, output)
1985
- end
1986
-
1987
- test 'converts inline SVG image using svg element even when data-uri is set' do
1988
- input = <<-EOS
1989
- :imagesdir: fixtures
1990
- :data-uri:
1991
-
1992
- [%inline]
1993
- image::circle.svg[Tiger,100]
1994
- EOS
1995
-
1996
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'docdir' => testdir }
1997
- assert_match(/<svg\s[^>]*width="100px">/, output, 1)
1998
- end
1999
-
2000
- test 'embeds remote inline SVG when allow-uri-read is set' do
2001
- input = <<-EOS
2002
- image::http://#{resolve_localhost}:9876/fixtures/circle.svg[Circle,100,100,opts=inline]
2003
- EOS
2004
-
2005
- output = using_test_webserver do
2006
- convert_string_to_embedded input, :safe => :safe, :attributes => {'allow-uri-read' => ''}
2007
- end
2008
-
2009
- assert_css 'svg', output, 1
2010
- assert_css 'svg[style]', output, 0
2011
- assert_css 'svg[width="100px"]', output, 1
2012
- assert_css 'svg[height="100px"]', output, 1
2013
- assert_css 'svg circle', output, 1
2014
- end
2015
-
2016
- test 'converts alt text for inline svg element if svg cannot be read' do
2017
- input = <<-EOS
2018
- [%inline]
2019
- image::no-such-image.svg[Alt Text]
2020
- EOS
2021
-
2022
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SERVER
2023
- assert_xpath '//span[@class="alt"][text()="Alt Text"]', output, 1
2024
- assert_message @logger, :WARN, '~SVG does not exist or cannot be read'
2025
- end
2026
-
2027
- test 'can convert block image with alt text defined in macro containing square bracket' do
2028
- input = <<-EOS
2029
- image::images/tiger.png[A [Bengal] Tiger]
2030
- EOS
2031
-
2032
- output = convert_string input
2033
- img = xmlnodes_at_xpath '//img', output, 1
2034
- assert_equal 'A [Bengal] Tiger', img.attr('alt')
2035
- end
2036
-
2037
- test 'can convert block image with target containing spaces' do
2038
- input = <<-EOS
2039
- image::images/big tiger.png[A Big Tiger]
2040
- EOS
2041
-
2042
- output = convert_string input
2043
- img = xmlnodes_at_xpath '//img', output, 1
2044
- assert_equal 'images/big%20tiger.png', img.attr('src')
2045
- assert_equal 'A Big Tiger', img.attr('alt')
2046
- end
2047
-
2048
- test 'should not recognize block image if target has leading or trailing spaces' do
2049
- [' tiger.png', 'tiger.png '].each do |target|
2050
- input = %(image::#{target}[Tiger])
2051
-
2052
- output = convert_string_to_embedded input
2053
- assert_xpath '//img', output, 0
2054
- end
2055
- end
2056
-
2057
- test 'can convert block image with alt text defined in block attribute above macro' do
2058
- input = <<-EOS
2059
- [Tiger]
2060
- image::images/tiger.png[]
2061
- EOS
2062
-
2063
- output = convert_string_to_embedded input
2064
- assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
2065
- end
2066
-
2067
- test 'alt text in macro overrides alt text above macro' do
2068
- input = <<-EOS
2069
- [Alt Text]
2070
- image::images/tiger.png[Tiger]
2071
- EOS
2072
-
2073
- output = convert_string_to_embedded input
2074
- assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
2075
- end
2076
-
2077
- test 'should substitute attribute references in alt text defined in image block macro' do
2078
- input = <<-EOS
2079
- :alt-text: Tiger
2080
-
2081
- image::images/tiger.png[{alt-text}]
2082
- EOS
2083
- output = convert_string_to_embedded input
2084
- assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
2085
- end
2086
-
2087
- test 'should set direction CSS class on image if float attribute is set' do
2088
- input = <<-EOS
2089
- [float=left]
2090
- image::images/tiger.png[Tiger]
2091
- EOS
2092
-
2093
- output = convert_string_to_embedded input
2094
- assert_css '.imageblock.left', output, 1
2095
- assert_css '.imageblock[style]', output, 0
2096
- end
2097
-
2098
- test 'should set text alignment CSS class on image if align attribute is set' do
2099
- input = <<-EOS
2100
- [align=center]
2101
- image::images/tiger.png[Tiger]
2102
- EOS
2103
-
2104
- output = convert_string_to_embedded input
2105
- assert_css '.imageblock.text-center', output, 1
2106
- assert_css '.imageblock[style]', output, 0
2107
- end
2108
-
2109
- test 'style attribute is dropped from image macro' do
2110
- input = <<-EOS
2111
- [style=value]
2112
- image::images/tiger.png[Tiger]
2113
- EOS
2114
-
2115
- doc = document_from_string input
2116
- img = doc.blocks[0]
2117
- refute(img.attributes.key? 'style')
2118
- assert_nil img.style
2119
- end
2120
-
2121
- test 'should apply specialcharacters and replacement substitutions to alt text' do
2122
- input = 'A tiger\'s "roar" is < a bear\'s "growl"'
2123
- expected = 'A tiger&#8217;s &quot;roar&quot; is &lt; a bear&#8217;s &quot;growl&quot;'
2124
- result = convert_string_to_embedded %(image::images/tiger-roar.png[#{input}])
2125
- assert_includes result, %(alt="#{expected}")
2126
- end
2127
-
2128
- test 'should not encode double quotes in alt text when converting to DocBook' do
2129
- input = 'Select "File > Open"'
2130
- expected = 'Select "File &gt; Open"'
2131
- result = convert_string_to_embedded %(image::images/open.png[#{input}]), :backend => :docbook
2132
- assert_includes result, %(<phrase>#{expected}</phrase>)
2133
- end
2134
-
2135
- test 'should auto-generate alt text for block image if alt text is not specified' do
2136
- input = <<-EOS
2137
- image::images/lions-and-tigers.png[]
2138
- EOS
2139
-
2140
- image = block_from_string input
2141
- assert_equal 'lions and tigers', (image.attr 'alt')
2142
- assert_equal 'lions and tigers', (image.attr 'default-alt')
2143
- output = image.convert
2144
- assert_xpath '/*[@class="imageblock"]//img[@src="images/lions-and-tigers.png"][@alt="lions and tigers"]', output, 1
2145
- end
2146
-
2147
- test "can convert block image with alt text and height and width" do
2148
- input = <<-EOS
2149
- image::images/tiger.png[Tiger, 200, 300]
2150
- EOS
2151
-
2152
- output = convert_string_to_embedded input
2153
- assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"][@width="200"][@height="300"]', output, 1
2154
- end
2155
-
2156
- test "can convert block image with link" do
2157
- input = <<-EOS
2158
- image::images/tiger.png[Tiger, link='http://en.wikipedia.org/wiki/Tiger']
2159
- EOS
2160
-
2161
- output = convert_string_to_embedded input
2162
- assert_xpath '/*[@class="imageblock"]//a[@class="image"][@href="http://en.wikipedia.org/wiki/Tiger"]/img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
2163
- end
2164
-
2165
- test 'adds rel=noopener attribute to block image with link that targets _blank window' do
2166
- input = <<-EOS
2167
- image::images/tiger.png[Tiger,link=http://en.wikipedia.org/wiki/Tiger,window=_blank]
2168
- EOS
2169
-
2170
- output = convert_string_to_embedded input
2171
- assert_xpath '/*[@class="imageblock"]//a[@class="image"][@href="http://en.wikipedia.org/wiki/Tiger"][@target="_blank"][@rel="noopener"]/img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
2172
- end
2173
-
2174
- test 'adds rel=noopener attribute to block image with link that targets name window when the noopener option is set' do
2175
- input = <<-EOS
2176
- image::images/tiger.png[Tiger,link=http://en.wikipedia.org/wiki/Tiger,window=name,opts=noopener]
2177
- EOS
2178
-
2179
- output = convert_string_to_embedded input
2180
- assert_xpath '/*[@class="imageblock"]//a[@class="image"][@href="http://en.wikipedia.org/wiki/Tiger"][@target="name"][@rel="noopener"]/img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
2181
- end
2182
-
2183
- test 'adds rel=nofollow attribute to block image with a link when the nofollow option is set' do
2184
- input = <<-EOS
2185
- image::images/tiger.png[Tiger,link=http://en.wikipedia.org/wiki/Tiger,opts=nofollow]
2186
- EOS
2187
-
2188
- output = convert_string_to_embedded input
2189
- assert_xpath '/*[@class="imageblock"]//a[@class="image"][@href="http://en.wikipedia.org/wiki/Tiger"][@rel="nofollow"]/img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
2190
- end
2191
-
2192
- test 'can convert block image with caption' do
2193
- input = <<-EOS
2194
- .The AsciiDoc Tiger
2195
- image::images/tiger.png[Tiger]
2196
- EOS
2197
-
2198
- doc = document_from_string input
2199
- assert_equal 1, doc.blocks[0].numeral
2200
- output = doc.convert
2201
- assert_xpath '//*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
2202
- assert_xpath '//*[@class="imageblock"]/*[@class="title"][text() = "Figure 1. The AsciiDoc Tiger"]', output, 1
2203
- assert_equal 1, doc.attributes['figure-number']
2204
- end
2205
-
2206
- test 'can convert block image with explicit caption' do
2207
- input = <<-EOS
2208
- [caption="Voila! "]
2209
- .The AsciiDoc Tiger
2210
- image::images/tiger.png[Tiger]
2211
- EOS
2212
-
2213
- doc = document_from_string input
2214
- assert_nil doc.blocks[0].numeral
2215
- output = doc.convert
2216
- assert_xpath '//*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
2217
- assert_xpath '//*[@class="imageblock"]/*[@class="title"][text() = "Voila! The AsciiDoc Tiger"]', output, 1
2218
- refute doc.attributes.has_key?('figure-number')
2219
- end
2220
-
2221
- test 'can align image in DocBook backend' do
2222
- input = <<-EOS
2223
- image::images/sunset.jpg[Sunset,align=right]
2224
- EOS
2225
-
2226
- output = convert_string_to_embedded input, :backend => :docbook
2227
- assert_xpath '//imagedata', output, 1
2228
- assert_xpath '//imagedata[@align="right"]', output, 1
2229
- end
2230
-
2231
- test 'should set content width and depth in DocBook backend if no scaling' do
2232
- input = <<-EOS
2233
- image::images/sunset.jpg[Sunset,500,332]
2234
- EOS
2235
-
2236
- output = convert_string_to_embedded input, :backend => :docbook
2237
- assert_xpath '//imagedata', output, 1
2238
- assert_xpath '//imagedata[@contentwidth="500"]', output, 1
2239
- assert_xpath '//imagedata[@contentdepth="332"]', output, 1
2240
- assert_xpath '//imagedata[@width]', output, 0
2241
- assert_xpath '//imagedata[@depth]', output, 0
2242
- end
2243
-
2244
- test 'can scale image in DocBook backend' do
2245
- input = <<-EOS
2246
- image::images/sunset.jpg[Sunset,500,332,scale=200]
2247
- EOS
2248
-
2249
- output = convert_string_to_embedded input, :backend => :docbook
2250
- assert_xpath '//imagedata', output, 1
2251
- assert_xpath '//imagedata[@scale="200"]', output, 1
2252
- assert_xpath '//imagedata[@width]', output, 0
2253
- assert_xpath '//imagedata[@depth]', output, 0
2254
- assert_xpath '//imagedata[@contentwidth]', output, 0
2255
- assert_xpath '//imagedata[@contentdepth]', output, 0
2256
- end
2257
-
2258
- test 'scale image width in DocBook backend' do
2259
- input = <<-EOS
2260
- image::images/sunset.jpg[Sunset,500,332,scaledwidth=25%]
2261
- EOS
2262
-
2263
- output = convert_string_to_embedded input, :backend => :docbook
2264
- assert_xpath '//imagedata', output, 1
2265
- assert_xpath '//imagedata[@width="25%"]', output, 1
2266
- assert_xpath '//imagedata[@depth]', output, 0
2267
- assert_xpath '//imagedata[@contentwidth]', output, 0
2268
- assert_xpath '//imagedata[@contentdepth]', output, 0
2269
- end
2270
-
2271
- test 'adds % to scaled width if no units given in DocBook backend ' do
2272
- input = <<-EOS
2273
- image::images/sunset.jpg[Sunset,scaledwidth=25]
2274
- EOS
2275
-
2276
- output = convert_string_to_embedded input, :backend => :docbook
2277
- assert_xpath '//imagedata', output, 1
2278
- assert_xpath '//imagedata[@width="25%"]', output, 1
2279
- end
2280
-
2281
- test 'keeps line unprocessed if image target is missing attribute reference and attribute-missing is skip' do
2282
- input = <<-EOS
2283
- :attribute-missing: skip
2284
-
2285
- image::{bogus}[]
2286
- EOS
2287
-
2288
- output = convert_string_to_embedded input
2289
- assert_includes output, 'image::{bogus}[]'
2290
- assert_message @logger, :WARN, 'dropping line containing reference to missing attribute: bogus'
2291
- end
2292
-
2293
- test 'drops line if image target is missing attribute reference and attribute-missing is drop' do
2294
- input = <<-EOS
2295
- :attribute-missing: drop
2296
-
2297
- image::{bogus}[]
2298
- EOS
2299
-
2300
- output = convert_string_to_embedded input
2301
- assert_empty output.strip
2302
- assert_message @logger, :WARN, 'dropping line containing reference to missing attribute: bogus'
2303
- end
2304
-
2305
- test 'drops line if image target is missing attribute reference and attribute-missing is drop-line' do
2306
- input = <<-EOS
2307
- :attribute-missing: drop-line
2308
-
2309
- image::{bogus}[]
2310
- EOS
2311
-
2312
- output = convert_string_to_embedded input
2313
- assert_empty output.strip
2314
- assert_message @logger, :WARN, 'dropping line containing reference to missing attribute: bogus'
2315
- end
2316
-
2317
- test 'dropped image does not break processing of following section and attribute-missing is drop-line' do
2318
- input = <<-EOS
2319
- :attribute-missing: drop-line
2320
-
2321
- image::{bogus}[]
2322
-
2323
- == Section Title
2324
- EOS
2325
-
2326
- output = convert_string_to_embedded input
2327
- assert_css 'img', output, 0
2328
- assert_css 'h2', output, 1
2329
- refute_includes output, '== Section Title'
2330
- assert_message @logger, :WARN, 'dropping line containing reference to missing attribute: bogus'
2331
- end
2332
-
2333
- test 'should pass through image that references uri' do
2334
- input = <<-EOS
2335
- :imagesdir: images
2336
-
2337
- image::http://asciidoc.org/images/tiger.png[Tiger]
2338
- EOS
2339
-
2340
- output = convert_string_to_embedded input
2341
- assert_xpath '/*[@class="imageblock"]//img[@src="http://asciidoc.org/images/tiger.png"][@alt="Tiger"]', output, 1
2342
- end
2343
-
2344
- test 'should encode spaces in image target if value is a URI' do
2345
- input = <<-EOS
2346
- image::http://example.org/svg?digraph=digraph G { a -> b; }[diagram]
2347
- EOS
2348
-
2349
- output = convert_string_to_embedded input
2350
- assert_xpath %(/*[@class="imageblock"]//img[@src="http://example.org/svg?digraph=digraph%20G%20{%20a%20-#{decode_char 62}%20b;%20}"]), output, 1
2351
- end
2352
-
2353
- test 'can resolve image relative to imagesdir' do
2354
- input = <<-EOS
2355
- :imagesdir: images
2356
-
2357
- image::tiger.png[Tiger]
2358
- EOS
2359
-
2360
- output = convert_string_to_embedded input
2361
- assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
2362
- end
2363
-
2364
- test 'embeds base64-encoded data uri for image when data-uri attribute is set' do
2365
- input = <<-EOS
2366
- :data-uri:
2367
- :imagesdir: fixtures
2368
-
2369
- image::dot.gif[Dot]
2370
- EOS
2371
-
2372
- doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => testdir }
2373
- assert_equal 'fixtures', doc.attributes['imagesdir']
2374
- output = doc.convert
2375
- assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
2376
- end
2377
-
2378
- test 'embeds empty base64-encoded data uri for unreadable image when data-uri attribute is set' do
2379
- input = <<-EOS
2380
- :data-uri:
2381
- :imagesdir: fixtures
2382
-
2383
- image::unreadable.gif[Dot]
2384
- EOS
2385
-
2386
- doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => testdir }
2387
- assert_equal 'fixtures', doc.attributes['imagesdir']
2388
- output = doc.convert
2389
- assert_xpath '//img[@src="data:image/gif;base64,"]', output, 1
2390
- assert_message @logger, :WARN, '~image to embed not found or not readable'
2391
- end
2392
-
2393
- test 'embeds base64-encoded data uri for remote image when data-uri attribute is set' do
2394
- input = <<-EOS
2395
- :data-uri:
2396
-
2397
- image::http://#{resolve_localhost}:9876/fixtures/dot.gif[Dot]
2398
- EOS
2399
-
2400
- output = using_test_webserver do
2401
- convert_string_to_embedded input, :safe => :safe, :attributes => {'allow-uri-read' => ''}
2402
- end
2403
-
2404
- assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
2405
- end
2406
-
2407
- test 'embeds base64-encoded data uri for remote image when imagesdir is a URI and data-uri attribute is set' do
2408
- input = <<-EOS
2409
- :data-uri:
2410
- :imagesdir: http://#{resolve_localhost}:9876/fixtures
2411
-
2412
- image::dot.gif[Dot]
2413
- EOS
2414
-
2415
- output = using_test_webserver do
2416
- convert_string_to_embedded input, :safe => :safe, :attributes => {'allow-uri-read' => ''}
2417
- end
2418
-
2419
- assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
2420
- end
2421
-
2422
- test 'uses remote image uri when data-uri attribute is set and image cannot be retrieved' do
2423
- image_uri = "http://#{resolve_localhost}:9876/fixtures/missing-image.gif"
2424
- input = <<-EOS
2425
- :data-uri:
2426
-
2427
- image::#{image_uri}[Missing image]
2428
- EOS
2429
-
2430
- output = using_test_webserver do
2431
- convert_string_to_embedded input, :safe => :safe, :attributes => {'allow-uri-read' => ''}
2432
- end
2433
-
2434
- assert_xpath %(/*[@class="imageblock"]//img[@src="#{image_uri}"][@alt="Missing image"]), output, 1
2435
- assert_message @logger, :WARN, '~could not retrieve image data from URI'
2436
- end
2437
-
2438
- test 'uses remote image uri when data-uri attribute is set and allow-uri-read is not set' do
2439
- image_uri = "http://#{resolve_localhost}:9876/fixtures/dot.gif"
2440
- input = <<-EOS
2441
- :data-uri:
2442
-
2443
- image::#{image_uri}[Dot]
2444
- EOS
2445
-
2446
- output = using_test_webserver do
2447
- convert_string_to_embedded input, :safe => :safe
2448
- end
2449
-
2450
- assert_xpath %(/*[@class="imageblock"]//img[@src="#{image_uri}"][@alt="Dot"]), output, 1
2451
- end
2452
-
2453
- test 'can handle embedded data uri images' do
2454
- input = <<-EOS
2455
- image::data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=[Dot]
2456
- EOS
2457
-
2458
- output = convert_string_to_embedded input
2459
- assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
2460
- end
2461
-
2462
- test 'can handle embedded data uri images when data-uri attribute is set' do
2463
- input = <<-EOS
2464
- :data-uri:
2465
-
2466
- image::data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=[Dot]
2467
- EOS
2468
-
2469
- output = convert_string_to_embedded input
2470
- assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
2471
- end
2472
-
2473
- test 'cleans reference to ancestor directories in imagesdir before reading image if safe mode level is at least SAFE' do
2474
- input = <<-EOS
2475
- :data-uri:
2476
- :imagesdir: ../..//fixtures/./../../fixtures
2477
-
2478
- image::dot.gif[Dot]
2479
- EOS
2480
-
2481
- doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => testdir }
2482
- assert_equal '../..//fixtures/./../../fixtures', doc.attributes['imagesdir']
2483
- output = doc.convert
2484
- # image target resolves to fixtures/dot.gif relative to docdir (which is explicitly set to the directory of this file)
2485
- # the reference cannot fall outside of the document directory in safe mode
2486
- assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
2487
- assert_message @logger, :WARN, 'image has illegal reference to ancestor of jail; recovering automatically'
2488
- end
2489
-
2490
- test 'cleans reference to ancestor directories in target before reading image if safe mode level is at least SAFE' do
2491
- input = <<-EOS
2492
- :data-uri:
2493
- :imagesdir: ./
2494
-
2495
- image::../..//fixtures/./../../fixtures/dot.gif[Dot]
2496
- EOS
2497
-
2498
- doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => { 'docdir' => testdir }
2499
- assert_equal './', doc.attributes['imagesdir']
2500
- output = doc.convert
2501
- # image target resolves to fixtures/dot.gif relative to docdir (which is explicitly set to the directory of this file)
2502
- # the reference cannot fall outside of the document directory in safe mode
2503
- assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
2504
- assert_message @logger, :WARN, 'image has illegal reference to ancestor of jail; recovering automatically'
2505
- end
2506
- end
2507
-
2508
- context 'Media' do
2509
- test 'should detect and convert video macro' do
2510
- input = <<-EOS
2511
- video::cats-vs-dogs.avi[]
2512
- EOS
2513
-
2514
- output = convert_string_to_embedded input
2515
- assert_css 'video', output, 1
2516
- assert_css 'video[src="cats-vs-dogs.avi"]', output, 1
2517
- end
2518
-
2519
- test 'should detect and convert video macro with positional attributes for poster and dimensions' do
2520
- input = <<-EOS
2521
- video::cats-vs-dogs.avi[cats-and-dogs.png, 200, 300]
2522
- EOS
2523
-
2524
- output = convert_string_to_embedded input
2525
- assert_css 'video', output, 1
2526
- assert_css 'video[src="cats-vs-dogs.avi"]', output, 1
2527
- assert_css 'video[poster="cats-and-dogs.png"]', output, 1
2528
- assert_css 'video[width="200"]', output, 1
2529
- assert_css 'video[height="300"]', output, 1
2530
- end
2531
-
2532
- test 'should set direction CSS class on video block if float attribute is set' do
2533
- input = <<-EOS
2534
- video::cats-vs-dogs.avi[cats-and-dogs.png,float=right]
2535
- EOS
2536
-
2537
- output = convert_string_to_embedded input
2538
- assert_css 'video', output, 1
2539
- assert_css 'video[src="cats-vs-dogs.avi"]', output, 1
2540
- assert_css '.videoblock.right', output, 1
2541
- end
2542
-
2543
- test 'should set text alignment CSS class on video block if align attribute is set' do
2544
- input = <<-EOS
2545
- video::cats-vs-dogs.avi[cats-and-dogs.png,align=center]
2546
- EOS
2547
-
2548
- output = convert_string_to_embedded input
2549
- assert_css 'video', output, 1
2550
- assert_css 'video[src="cats-vs-dogs.avi"]', output, 1
2551
- assert_css '.videoblock.text-center', output, 1
2552
- end
2553
-
2554
- test 'video macro should honor all options' do
2555
- input = <<-EOS
2556
- video::cats-vs-dogs.avi[options="autoplay,nocontrols,loop",preload="metadata"]
2557
- EOS
2558
-
2559
- output = convert_string_to_embedded input
2560
- assert_css 'video', output, 1
2561
- assert_css 'video[autoplay]', output, 1
2562
- assert_css 'video:not([controls])', output, 1
2563
- assert_css 'video[loop]', output, 1
2564
- assert_css 'video[preload=metadata]', output, 1
2565
- end
2566
-
2567
- test 'video macro should add time range anchor with start time if start attribute is set' do
2568
- input = <<-EOS
2569
- video::cats-vs-dogs.avi[start="30"]
2570
- EOS
2571
-
2572
- output = convert_string_to_embedded input
2573
- assert_css 'video', output, 1
2574
- assert_xpath '//video[@src="cats-vs-dogs.avi#t=30"]', output, 1
2575
- end
2576
-
2577
- test 'video macro should add time range anchor with end time if end attribute is set' do
2578
- input = <<-EOS
2579
- video::cats-vs-dogs.avi[end="30"]
2580
- EOS
2581
-
2582
- output = convert_string_to_embedded input
2583
- assert_css 'video', output, 1
2584
- assert_xpath '//video[@src="cats-vs-dogs.avi#t=,30"]', output, 1
2585
- end
2586
-
2587
- test 'video macro should add time range anchor with start and end time if start and end attributes are set' do
2588
- input = <<-EOS
2589
- video::cats-vs-dogs.avi[start="30",end="60"]
2590
- EOS
2591
-
2592
- output = convert_string_to_embedded input
2593
- assert_css 'video', output, 1
2594
- assert_xpath '//video[@src="cats-vs-dogs.avi#t=30,60"]', output, 1
2595
- end
2596
-
2597
- test 'video macro should use imagesdir attribute to resolve target and poster' do
2598
- input = <<-EOS
2599
- :imagesdir: assets
2600
-
2601
- video::cats-vs-dogs.avi[cats-and-dogs.png, 200, 300]
2602
- EOS
2603
-
2604
- output = convert_string_to_embedded input
2605
- assert_css 'video', output, 1
2606
- assert_css 'video[src="assets/cats-vs-dogs.avi"]', output, 1
2607
- assert_css 'video[poster="assets/cats-and-dogs.png"]', output, 1
2608
- assert_css 'video[width="200"]', output, 1
2609
- assert_css 'video[height="300"]', output, 1
2610
- end
2611
-
2612
- test 'video macro should not use imagesdir attribute to resolve target if target is a URL' do
2613
- input = <<-EOS
2614
- :imagesdir: assets
2615
-
2616
- video::http://example.org/videos/cats-vs-dogs.avi[]
2617
- EOS
2618
-
2619
- output = convert_string_to_embedded input
2620
- assert_css 'video', output, 1
2621
- assert_css 'video[src="http://example.org/videos/cats-vs-dogs.avi"]', output, 1
2622
- end
2623
-
2624
- test 'video macro should output custom HTML with iframe for vimeo service' do
2625
- input = <<-EOS
2626
- video::67480300[vimeo, 400, 300, start=60, options=autoplay]
2627
- EOS
2628
- output = convert_string_to_embedded input
2629
- assert_css 'video', output, 0
2630
- assert_css 'iframe', output, 1
2631
- assert_css 'iframe[src="https://player.vimeo.com/video/67480300#at=60?autoplay=1"]', output, 1
2632
- assert_css 'iframe[width="400"]', output, 1
2633
- assert_css 'iframe[height="300"]', output, 1
2634
- end
2635
-
2636
- test 'video macro should output custom HTML with iframe for youtube service' do
2637
- input = <<-EOS
2638
- video::U8GBXvdmHT4/PLg7s6cbtAD15Das5LK9mXt_g59DLWxKUe[youtube, 640, 360, start=60, options="autoplay,modest", theme=light]
2639
- EOS
2640
- output = convert_string_to_embedded input
2641
- assert_css 'video', output, 0
2642
- assert_css 'iframe', output, 1
2643
- assert_css 'iframe[src="https://www.youtube.com/embed/U8GBXvdmHT4?rel=0&start=60&autoplay=1&list=PLg7s6cbtAD15Das5LK9mXt_g59DLWxKUe&modestbranding=1&theme=light"]', output, 1
2644
- assert_css 'iframe[width="640"]', output, 1
2645
- assert_css 'iframe[height="360"]', output, 1
2646
- end
2647
-
2648
- test 'video macro should output custom HTML with iframe for youtube service with dynamic playlist' do
2649
- input = <<-EOS
2650
- video::SCZF6I-Rc4I,AsKGOeonbIs,HwrPhOp6-aM[youtube, 640, 360, start=60, options=autoplay]
2651
- EOS
2652
- output = convert_string_to_embedded input
2653
- assert_css 'video', output, 0
2654
- assert_css 'iframe', output, 1
2655
- assert_css 'iframe[src="https://www.youtube.com/embed/SCZF6I-Rc4I?rel=0&start=60&autoplay=1&playlist=AsKGOeonbIs,HwrPhOp6-aM"]', output, 1
2656
- assert_css 'iframe[width="640"]', output, 1
2657
- assert_css 'iframe[height="360"]', output, 1
2658
- end
2659
-
2660
- test 'should detect and convert audio macro' do
2661
- input = <<-EOS
2662
- audio::podcast.mp3[]
2663
- EOS
2664
-
2665
- output = convert_string_to_embedded input
2666
- assert_css 'audio', output, 1
2667
- assert_css 'audio[src="podcast.mp3"]', output, 1
2668
- end
2669
-
2670
- test 'audio macro should use imagesdir attribute to resolve target' do
2671
- input = <<-EOS
2672
- :imagesdir: assets
2673
-
2674
- audio::podcast.mp3[]
2675
- EOS
2676
-
2677
- output = convert_string_to_embedded input
2678
- assert_css 'audio', output, 1
2679
- assert_css 'audio[src="assets/podcast.mp3"]', output, 1
2680
- end
2681
-
2682
- test 'audio macro should not use imagesdir attribute to resolve target if target is a URL' do
2683
- input = <<-EOS
2684
- :imagesdir: assets
2685
-
2686
- video::http://example.org/podcast.mp3[]
2687
- EOS
2688
-
2689
- output = convert_string_to_embedded input
2690
- assert_css 'video', output, 1
2691
- assert_css 'video[src="http://example.org/podcast.mp3"]', output, 1
2692
- end
2693
-
2694
- test 'audio macro should honor all options' do
2695
- input = <<-EOS
2696
- audio::podcast.mp3[options="autoplay,nocontrols,loop"]
2697
- EOS
2698
-
2699
- output = convert_string_to_embedded input
2700
- assert_css 'audio', output, 1
2701
- assert_css 'audio[autoplay]', output, 1
2702
- assert_css 'audio:not([controls])', output, 1
2703
- assert_css 'audio[loop]', output, 1
2704
- end
2705
-
2706
- test 'audio macro should support start and end time' do
2707
- input = <<-EOS
2708
- audio::podcast.mp3[start=1,end=2]
2709
- EOS
2710
-
2711
- output = convert_string_to_embedded input
2712
- assert_css 'audio', output, 1
2713
- assert_css 'audio[controls]', output, 1
2714
- assert_css 'audio[src="podcast.mp3#t=1,2"]', output, 1
2715
- end
2716
- end
2717
-
2718
- context 'Admonition icons' do
2719
- test 'can resolve icon relative to default iconsdir' do
2720
- input = <<-EOS
2721
- :icons:
2722
-
2723
- [TIP]
2724
- You can use icons for admonitions by setting the 'icons' attribute.
2725
- EOS
2726
-
2727
- output = convert_string input, :safe => Asciidoctor::SafeMode::SERVER
2728
- assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="./images/icons/tip.png"][@alt="Tip"]', output, 1
2729
- end
2730
-
2731
- test 'can resolve icon relative to custom iconsdir' do
2732
- input = <<-EOS
2733
- :icons:
2734
- :iconsdir: icons
2735
-
2736
- [TIP]
2737
- You can use icons for admonitions by setting the 'icons' attribute.
2738
- EOS
2739
-
2740
- output = convert_string input, :safe => Asciidoctor::SafeMode::SERVER
2741
- assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="icons/tip.png"][@alt="Tip"]', output, 1
2742
- end
2743
-
2744
- test 'should add file extension to custom icon if not specified' do
2745
- input = <<-EOS
2746
- :icons: font
2747
- :iconsdir: images/icons
2748
-
2749
- [TIP,icon=a]
2750
- Override the icon of an admonition block using an attribute
2751
- EOS
2752
-
2753
- output = convert_string input, :safe => Asciidoctor::SafeMode::SERVER
2754
- assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="images/icons/a.png"]', output, 1
2755
- end
2756
-
2757
- test 'embeds base64-encoded data uri of icon when data-uri attribute is set and safe mode level is less than SECURE' do
2758
- input = <<-EOS
2759
- :icons:
2760
- :iconsdir: fixtures
2761
- :icontype: gif
2762
- :data-uri:
2763
-
2764
- [TIP]
2765
- You can use icons for admonitions by setting the 'icons' attribute.
2766
- EOS
2767
-
2768
- output = convert_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => { 'docdir' => testdir }
2769
- assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Tip"]', output, 1
2770
- end
2771
-
2772
- test 'should embed base64-encoded data uri of custom icon when data-uri attribute is set' do
2773
- input = <<-EOS
2774
- :icons:
2775
- :iconsdir: fixtures
2776
- :icontype: gif
2777
- :data-uri:
2778
-
2779
- [TIP,icon=tip]
2780
- You can set a custom icon using the icon attribute on the block.
2781
- EOS
2782
-
2783
- output = convert_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => { 'docdir' => testdir }
2784
- assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Tip"]', output, 1
2785
- end
2786
-
2787
- test 'does not embed base64-encoded data uri of icon when safe mode level is SECURE or greater' do
2788
- input = <<-EOS
2789
- :icons:
2790
- :iconsdir: fixtures
2791
- :icontype: gif
2792
- :data-uri:
2793
-
2794
- [TIP]
2795
- You can use icons for admonitions by setting the 'icons' attribute.
2796
- EOS
2797
-
2798
- output = convert_string input, :attributes => {'icons' => ''}
2799
- assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="fixtures/tip.gif"][@alt="Tip"]', output, 1
2800
- end
2801
-
2802
- test 'cleans reference to ancestor directories before reading icon if safe mode level is at least SAFE' do
2803
- input = <<-EOS
2804
- :icons:
2805
- :iconsdir: ../fixtures
2806
- :icontype: gif
2807
- :data-uri:
2808
-
2809
- [TIP]
2810
- You can use icons for admonitions by setting the 'icons' attribute.
2811
- EOS
2812
-
2813
- output = convert_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => { 'docdir' => testdir }
2814
- assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Tip"]', output, 1
2815
- assert_message @logger, :WARN, 'image has illegal reference to ancestor of jail; recovering automatically'
2816
- end
2817
-
2818
- test 'should import Font Awesome and use font-based icons when value of icons attribute is font' do
2819
- input = <<-EOS
2820
- :icons: font
2821
-
2822
- [TIP]
2823
- You can use icons for admonitions by setting the 'icons' attribute.
2824
- EOS
2825
-
2826
- output = convert_string input, :safe => Asciidoctor::SafeMode::SERVER
2827
- assert_css %(html > head > link[rel="stylesheet"][href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/#{Asciidoctor::FONT_AWESOME_VERSION}/css/font-awesome.min.css"]), output, 1
2828
- assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/i[@class="fa icon-tip"]', output, 1
2829
- end
2830
-
2831
- test 'font-based icon should not override icon specified on admonition' do
2832
- input = <<-EOS
2833
- :icons: font
2834
- :iconsdir: images/icons
2835
-
2836
- [TIP,icon=a.png]
2837
- Override the icon of an admonition block using an attribute
2838
- EOS
2839
-
2840
- output = convert_string input, :safe => Asciidoctor::SafeMode::SERVER
2841
- assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/i[@class="fa icon-tip"]', output, 0
2842
- assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="images/icons/a.png"]', output, 1
2843
- end
2844
-
2845
- test 'should use http uri scheme for assets when asset-uri-scheme is http' do
2846
- input = <<-EOS
2847
- :asset-uri-scheme: http
2848
- :icons: font
2849
- :source-highlighter: highlightjs
2850
-
2851
- TIP: You can control the URI scheme used for assets with the asset-uri-scheme attribute
2852
-
2853
- [source,ruby]
2854
- puts "AsciiDoc, FTW!"
2855
- EOS
2856
-
2857
- output = convert_string input, :safe => Asciidoctor::SafeMode::SAFE
2858
- assert_css %(html > head > link[rel="stylesheet"][href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/#{Asciidoctor::FONT_AWESOME_VERSION}/css/font-awesome.min.css"]), output, 1
2859
- assert_css 'html > body > script[src="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/highlight.min.js"]', output, 1
2860
- end
2861
-
2862
- test 'should use no uri scheme for assets when asset-uri-scheme is blank' do
2863
- input = <<-EOS
2864
- :asset-uri-scheme:
2865
- :icons: font
2866
- :source-highlighter: highlightjs
2867
-
2868
- TIP: You can control the URI scheme used for assets with the asset-uri-scheme attribute
2869
-
2870
- [source,ruby]
2871
- puts "AsciiDoc, FTW!"
2872
- EOS
2873
-
2874
- output = convert_string input, :safe => Asciidoctor::SafeMode::SAFE
2875
- assert_css %(html > head > link[rel="stylesheet"][href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/#{Asciidoctor::FONT_AWESOME_VERSION}/css/font-awesome.min.css"]), output, 1
2876
- assert_css 'html > body > script[src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/highlight.min.js"]', output, 1
2877
- end
2878
- end
2879
-
2880
- context 'Image paths' do
2881
- test 'restricts access to ancestor directories when safe mode level is at least SAFE' do
2882
- input = <<-EOS
2883
- image::asciidoctor.png[Asciidoctor]
2884
- EOS
2885
- basedir = testdir
2886
- block = block_from_string input, :attributes => {'docdir' => basedir}
2887
- doc = block.document
2888
- assert doc.safe >= Asciidoctor::SafeMode::SAFE
2889
-
2890
- assert_equal File.join(basedir, 'images'), block.normalize_asset_path('images')
2891
- assert_equal File.join(basedir, 'etc/images'), block.normalize_asset_path("#{disk_root}etc/images")
2892
- assert_equal File.join(basedir, 'images'), block.normalize_asset_path('../../images')
2893
- end
2894
-
2895
- test 'does not restrict access to ancestor directories when safe mode is disabled' do
2896
- input = <<-EOS
2897
- image::asciidoctor.png[Asciidoctor]
2898
- EOS
2899
- basedir = testdir
2900
- block = block_from_string input, :safe => Asciidoctor::SafeMode::UNSAFE, :attributes => {'docdir' => basedir}
2901
- doc = block.document
2902
- assert doc.safe == Asciidoctor::SafeMode::UNSAFE
2903
-
2904
- assert_equal File.join(basedir, 'images'), block.normalize_asset_path('images')
2905
- absolute_path = "#{disk_root}etc/images"
2906
- assert_equal absolute_path, block.normalize_asset_path(absolute_path)
2907
- assert_equal File.expand_path(File.join(basedir, '../../images')), block.normalize_asset_path('../../images')
2908
- end
2909
-
2910
- end
2911
-
2912
- context 'Source code' do
2913
- test 'should support fenced code block using backticks' do
2914
- input = <<-EOS
2915
- ```
2916
- puts "Hello, World!"
2917
- ```
2918
- EOS
2919
-
2920
- output = convert_string_to_embedded input
2921
- assert_css '.listingblock', output, 1
2922
- assert_css '.listingblock pre code', output, 1
2923
- assert_css '.listingblock pre code:not([class])', output, 1
2924
- end
2925
-
2926
- test 'should not recognize fenced code blocks with more than three delimiters' do
2927
- input = <<-EOS
2928
- ````ruby
2929
- puts "Hello, World!"
2930
- ````
2931
-
2932
- ~~~~ javascript
2933
- alert("Hello, World!")
2934
- ~~~~
2935
- EOS
2936
-
2937
- output = convert_string_to_embedded input
2938
- assert_css '.listingblock', output, 0
2939
- end
2940
-
2941
- test 'should support fenced code blocks with languages' do
2942
- input = <<-EOS
2943
- ```ruby
2944
- puts "Hello, World!"
2945
- ```
2946
-
2947
- ``` javascript
2948
- alert("Hello, World!")
2949
- ```
2950
- EOS
2951
-
2952
- output = convert_string_to_embedded input
2953
- assert_css '.listingblock', output, 2
2954
- assert_css '.listingblock pre code.language-ruby[data-lang=ruby]', output, 1
2955
- assert_css '.listingblock pre code.language-javascript[data-lang=javascript]', output, 1
2956
- end
2957
-
2958
- test 'should support fenced code blocks with languages and numbering' do
2959
- input = <<-EOS
2960
- ```ruby,numbered
2961
- puts "Hello, World!"
2962
- ```
2963
-
2964
- ``` javascript, numbered
2965
- alert("Hello, World!")
2966
- ```
2967
- EOS
2968
-
2969
- output = convert_string_to_embedded input
2970
- assert_css '.listingblock', output, 2
2971
- assert_css '.listingblock pre code.language-ruby[data-lang=ruby]', output, 1
2972
- assert_css '.listingblock pre code.language-javascript[data-lang=javascript]', output, 1
2973
- end
2974
-
2975
- test 'should highlight source if source-highlighter attribute is coderay' do
2976
- input = <<-EOS
2977
- :source-highlighter: coderay
2978
-
2979
- [source, ruby]
2980
- ----
2981
- require 'coderay'
2982
-
2983
- html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table)
2984
- ----
2985
- EOS
2986
- output = convert_string input, :safe => Asciidoctor::SafeMode::SAFE, :linkcss_default => true
2987
- assert_xpath '//pre[@class="CodeRay highlight"]/code[@data-lang="ruby"]//span[@class = "constant"][text() = "CodeRay"]', output, 1
2988
- assert_match(/\.CodeRay *\{/, output)
2989
- end
2990
-
2991
- test 'should number lines if third positional attribute is set' do
2992
- input = <<-EOS
2993
- :source-highlighter: coderay
2994
-
2995
- [source,ruby,linenums]
2996
- ----
2997
- puts 'Hello, World!'
2998
- ----
2999
- EOS
3000
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SAFE
3001
- assert_xpath '//td[@class="line-numbers"]', output, 1
3002
- end
3003
-
3004
- test 'should number lines if linenums option is set on source block' do
3005
- input = <<-EOS
3006
- :source-highlighter: coderay
3007
-
3008
- [source%linenums,ruby]
3009
- ----
3010
- puts 'Hello, World!'
3011
- ----
3012
- EOS
3013
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SAFE
3014
- assert_xpath '//td[@class="line-numbers"]', output, 1
3015
- end
3016
-
3017
- test 'should number lines of source block if source-linenums-option document attribute is set' do
3018
- input = <<-EOS
3019
- :source-highlighter: coderay
3020
- :source-linenums-option:
3021
-
3022
- [source,ruby]
3023
- ----
3024
- puts 'Hello, World!'
3025
- ----
3026
- EOS
3027
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SAFE
3028
- assert_xpath '//td[@class="line-numbers"]', output, 1
3029
- end
3030
-
3031
- test 'should set starting line number in HTML output if linenums option is enabled and start attribute is set' do
3032
- input = <<-EOS
3033
- :source-highlighter: coderay
3034
- :coderay-linenums-mode: inline
3035
-
3036
- [source%linenums,ruby,start=10]
3037
- ----
3038
- puts 'Hello, World!'
3039
- ----
3040
- EOS
3041
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SAFE
3042
- assert_xpath '//span[@class="line-numbers"]', output, 1
3043
- assert_xpath '//span[@class="line-numbers"][text()="10"]', output, 1
3044
- end
3045
-
3046
- test 'should set starting line number in DocBook output if linenums option is enabled and start attribute is set' do
3047
- input = <<-EOS
3048
- [source%linenums,java,start=3]
3049
- ----
3050
- public class HelloWorld {
3051
- public static void main(String[] args) {
3052
- out.println("Hello, World!");
3053
- }
3054
- }
3055
- ----
3056
- EOS
3057
-
3058
- output = convert_string_to_embedded input, :backend => :docbook, :safe => Asciidoctor::SafeMode::SAFE
3059
- assert_css 'programlisting[startinglinenumber]', output, 1
3060
- assert_css 'programlisting[startinglinenumber="3"]', output, 1
3061
- end
3062
-
3063
- test 'should highlight lines specified in highlight attribute if linenums is set and source-highlighter is coderay' do
3064
- %w(highlight="1,4-6" highlight=1;4..6 highlight=1;4..;!7).each do |highlight_attr|
3065
- input = <<-EOS
3066
- :source-highlighter: coderay
3067
-
3068
- [source%linenums,java,#{highlight_attr}]
3069
- ----
3070
- import static java.lang.System.out;
3071
-
3072
- public class HelloWorld {
3073
- public static void main(String[] args) {
3074
- out.println("Hello, World!");
3075
- }
3076
- }
3077
- ----
3078
- EOS
3079
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SAFE
3080
- assert_css 'strong.highlighted', output, 4
3081
- assert_xpath '//strong[@class="highlighted"][text()="1"]', output, 1
3082
- assert_xpath '//strong[@class="highlighted"][text()="2"]', output, 0
3083
- assert_xpath '//strong[@class="highlighted"][text()="3"]', output, 0
3084
- assert_xpath '//strong[@class="highlighted"][text()="4"]', output, 1
3085
- assert_xpath '//strong[@class="highlighted"][text()="5"]', output, 1
3086
- assert_xpath '//strong[@class="highlighted"][text()="6"]', output, 1
3087
- assert_xpath '//strong[@class="highlighted"][text()="7"]', output, 0
3088
- end
3089
- end
3090
-
3091
- test 'should read source language from source-language document attribute if not specified on source block' do
3092
- input = <<-EOS
3093
- :source-highlighter: coderay
3094
- :source-language: ruby
3095
-
3096
- [source]
3097
- ----
3098
- require 'coderay'
3099
-
3100
- html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table)
3101
- ----
3102
- EOS
3103
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SAFE, :linkcss_default => true
3104
- assert_xpath '//pre[@class="CodeRay highlight"]/code[@data-lang="ruby"]//span[@class = "constant"][text() = "CodeRay"]', output, 1
3105
- end
3106
-
3107
- test 'should rename document attribute named language to source-language when compat-mode is enabled' do
3108
- input = <<-EOS
3109
- :language: ruby
3110
-
3111
- {source-language}
3112
- EOS
3113
-
3114
- assert_equal 'ruby', (convert_inline_string input, :attributes => {'compat-mode' => ''})
3115
-
3116
- input = <<-EOS
3117
- :language: ruby
3118
-
3119
- {source-language}
3120
- EOS
3121
-
3122
- assert_equal '{source-language}', (convert_inline_string input)
3123
- end
3124
-
3125
- test 'should replace callout marks but not highlight them if source-highlighter attribute is coderay' do
3126
- input = <<-EOS
3127
- :source-highlighter: coderay
3128
-
3129
- [source, ruby]
3130
- ----
3131
- require 'coderay' # <1>
3132
-
3133
- html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table) # <2>
3134
- puts html # <3> <4>
3135
- exit 0 # <5><6>
3136
- ----
3137
- <1> Load library
3138
- <2> Highlight source
3139
- <3> Print to stdout
3140
- <4> Redirect to a file to capture output
3141
- <5> Exit program
3142
- <6> Reports success
3143
- EOS
3144
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SAFE
3145
- assert_match(/<span class="content">coderay<\/span>.* # <b class="conum">\(1\)<\/b>$/, output)
3146
- assert_match(/<span class="content">puts 'Hello, world!'<\/span>.* # <b class="conum">\(2\)<\/b>$/, output)
3147
- assert_match(/puts html.* # <b class="conum">\(3\)<\/b> <b class="conum">\(4\)<\/b>$/, output)
3148
- assert_match(/exit.* # <b class="conum">\(5\)<\/b> <b class="conum">\(6\)<\/b><\/code>/, output)
3149
- end
3150
-
3151
- test 'should support autonumbered callout marks if source-highlighter attribute is coderay' do
3152
- input = <<-EOS
3153
- :source-highlighter: coderay
3154
-
3155
- [source, ruby]
3156
- ----
3157
- require 'coderay' # <.><.>
3158
-
3159
- html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table) # <.>
3160
- puts html # <.>
3161
- ----
3162
- <.> Load library
3163
- <.> Gem must be installed
3164
- <.> Highlight source
3165
- <.> Print to stdout
3166
- EOS
3167
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SAFE
3168
- assert_match(/<span class="content">coderay<\/span>.* # <b class="conum">\(1\)<\/b> <b class="conum">\(2\)<\/b>$/, output)
3169
- assert_match(/<span class="content">puts 'Hello, world!'<\/span>.* # <b class="conum">\(3\)<\/b>$/, output)
3170
- assert_match(/puts html.* # <b class="conum">\(4\)<\/b><\/code>/, output)
3171
- assert_css '.colist ol', output, 1
3172
- assert_css '.colist ol li', output, 4
3173
- end
3174
-
3175
- test 'should restore callout marks to correct lines if source highlighter is coderay and table line numbering is enabled' do
3176
- input = <<-EOS
3177
- :source-highlighter: coderay
3178
- :coderay-linenums-mode: table
3179
-
3180
- [source, ruby, numbered]
3181
- ----
3182
- require 'coderay' # <1>
3183
-
3184
- html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table) # <2>
3185
- puts html # <3> <4>
3186
- exit 0 # <5><6>
3187
- ----
3188
- <1> Load library
3189
- <2> Highlight source
3190
- <3> Print to stdout
3191
- <4> Redirect to a file to capture output
3192
- <5> Exit program
3193
- <6> Reports success
3194
- EOS
3195
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SAFE
3196
- assert_match(/<span class="content">coderay<\/span>.* # <b class="conum">\(1\)<\/b>$/, output)
3197
- assert_match(/<span class="content">puts 'Hello, world!'<\/span>.* # <b class="conum">\(2\)<\/b>$/, output)
3198
- assert_match(/puts html.* # <b class="conum">\(3\)<\/b> <b class="conum">\(4\)<\/b>$/, output)
3199
- assert_match(/exit.* # <b class="conum">\(5\)<\/b> <b class="conum">\(6\)<\/b><\/pre>/, output)
3200
- end
3201
-
3202
- test 'should preserve space before callout on final line' do
3203
- inputs = []
3204
-
3205
- inputs << <<-EOS
3206
- [source,yaml]
3207
- ----
3208
- a: 'a'
3209
- key: 'value' #<1>
3210
- ----
3211
- <1> key-value pair
3212
- EOS
3213
-
3214
- inputs << <<-EOS
3215
- [source,ruby]
3216
- ----
3217
- puts 'hi'
3218
- puts 'value' #<1>
3219
- ----
3220
- <1> print to stdout
3221
- EOS
3222
-
3223
- inputs << <<-EOS
3224
- [source,python]
3225
- ----
3226
- print 'hi'
3227
- print 'value' #<1>
3228
- ----
3229
- <1> print to stdout
3230
- EOS
3231
-
3232
- inputs.each do |input|
3233
- output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => { 'source-highlighter' => 'coderay' }
3234
- output = output.gsub(/<\/?span.*?>/, '')
3235
- assert_includes output, '\'value\' #<b class="conum">(1)</b>'
3236
- end
3237
- end
3238
-
3239
- test 'should preserve passthrough placeholders when highlighting source using coderay' do
3240
- input = <<-EOS
3241
- :source-highlighter: coderay
3242
-
3243
- [source,java]
3244
- [subs="specialcharacters,macros,callouts"]
3245
- ----
3246
- public class Printer {
3247
- public static void main(String[] args) {
3248
- System.pass:quotes[_out_].println("*asterisks* make text pass:quotes[*bold*]");
3249
- }
3250
- }
3251
- ----
3252
- EOS
3253
- output = convert_string input, :safe => Asciidoctor::SafeMode::SAFE
3254
- assert_match(/\.<em>out<\/em>\./, output, 1)
3255
- assert_match(/\*asterisks\*/, output, 1)
3256
- assert_match(/<strong>bold<\/strong>/, output, 1)
3257
- refute_includes output, Asciidoctor::Substitutors::PASS_START
3258
- end
3259
-
3260
- test 'should link to CodeRay stylesheet if source-highlighter is coderay and linkcss is set' do
3261
- input = <<-EOS
3262
- :source-highlighter: coderay
3263
-
3264
- [source, ruby]
3265
- ----
3266
- require 'coderay'
3267
-
3268
- html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table)
3269
- ----
3270
- EOS
3271
- output = convert_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'linkcss' => ''}
3272
- assert_xpath '//pre[@class="CodeRay highlight"]/code[@data-lang="ruby"]//span[@class = "constant"][text() = "CodeRay"]', output, 1
3273
- assert_css 'link[rel="stylesheet"][href="./coderay-asciidoctor.css"]', output, 1
3274
- end
3275
-
3276
- test 'should highlight source inline if source-highlighter attribute is coderay and coderay-css is style' do
3277
- input = <<-EOS
3278
- :source-highlighter: coderay
3279
- :coderay-css: style
3280
-
3281
- [source, ruby]
3282
- ----
3283
- require 'coderay'
3284
-
3285
- html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table)
3286
- ----
3287
- EOS
3288
- output = convert_string input, :safe => Asciidoctor::SafeMode::SAFE, :linkcss_default => true
3289
- assert_xpath '//pre[@class="CodeRay highlight"]/code[@data-lang="ruby"]//span[@style = "color:#036;font-weight:bold"][text() = "CodeRay"]', output, 1
3290
- refute_match(/\.CodeRay \{/, output)
3291
- end
3292
-
3293
- test 'should include remote highlight.js assets if source-highlighter attribute is highlightjs' do
3294
- input = <<-EOS
3295
- :source-highlighter: highlightjs
3296
-
3297
- [source, javascript]
3298
- ----
3299
- <link rel="stylesheet" href="styles/default.css">
3300
- <script src="highlight.pack.js"></script>
3301
- <script>hljs.initHighlightingOnLoad();</script>
3302
- ----
3303
- EOS
3304
- output = convert_string input, :safe => Asciidoctor::SafeMode::SAFE
3305
- assert_match(/<link .*highlight\.js/, output)
3306
- assert_match(/<script .*highlight\.js/, output)
3307
- assert_match(/hljs.initHighlightingOnLoad/, output)
3308
- end
3309
-
3310
- test 'should add language classes to child code element when source-highlighter is prettify' do
3311
- input = <<-EOS
3312
- [source,ruby]
3313
- ----
3314
- puts "foo"
3315
- ----
3316
- EOS
3317
-
3318
- output = convert_string_to_embedded input, :attributes => {'source-highlighter' => 'prettify'}
3319
- assert_css 'pre[class="prettyprint highlight"]', output, 1
3320
- assert_css 'pre > code.language-ruby[data-lang="ruby"]', output, 1
3321
- end
3322
-
3323
- test 'should set lang attribute on pre when source-highlighter is html-pipeline' do
3324
- input = <<-EOS
3325
- [source,ruby]
3326
- ----
3327
- filters = [
3328
- HTML::Pipeline::AsciiDocFilter,
3329
- HTML::Pipeline::SanitizationFilter,
3330
- HTML::Pipeline::SyntaxHighlightFilter
3331
- ]
3332
-
3333
- puts HTML::Pipeline.new(filters, {}).call(input)[:output]
3334
- ----
3335
- EOS
3336
-
3337
- output = convert_string input, :attributes => {'source-highlighter' => 'html-pipeline'}
3338
- assert_css 'pre[lang="ruby"]', output, 1
3339
- assert_css 'pre[lang="ruby"] > code', output, 1
3340
- assert_css 'pre[class]', output, 0
3341
- assert_css 'code[class]', output, 0
3342
- end
3343
-
3344
- test 'document cannot turn on source highlighting if safe mode is at least SERVER' do
3345
- input = <<-EOS
3346
- :source-highlighter: coderay
3347
- EOS
3348
- doc = document_from_string input, :safe => Asciidoctor::SafeMode::SERVER
3349
- assert_nil doc.attributes['source-highlighter']
3350
- end
3351
-
3352
- test 'should warn if listing block is not terminated' do
3353
- input = <<-EOS
3354
- outside
3355
-
3356
- ----
3357
- inside
3358
-
3359
- still inside
3360
-
3361
- eof
3362
- EOS
3363
-
3364
- output = convert_string_to_embedded input
3365
- assert_xpath '/*[@class="listingblock"]', output, 1
3366
- assert_message @logger, :WARN, '<stdin>: line 3: unterminated listing block', Hash
3367
- end
3368
- end
3369
-
3370
- context 'Abstract and Part Intro' do
3371
- test 'should make abstract on open block without title a quote block for article' do
3372
- input = <<-EOS
3373
- = Article
3374
-
3375
- [abstract]
3376
- --
3377
- This article is about stuff.
3378
-
3379
- And other stuff.
3380
- --
3381
-
3382
- == Section One
3383
-
3384
- content
3385
- EOS
3386
-
3387
- output = convert_string input
3388
- assert_css '.quoteblock', output, 1
3389
- assert_css '.quoteblock.abstract', output, 1
3390
- assert_css '#preamble .quoteblock', output, 1
3391
- assert_css '.quoteblock > blockquote', output, 1
3392
- assert_css '.quoteblock > blockquote > .paragraph', output, 2
3393
- end
3394
-
3395
- test 'should make abstract on open block with title a quote block with title for article' do
3396
- input = <<-EOS
3397
- = Article
3398
-
3399
- .My abstract
3400
- [abstract]
3401
- --
3402
- This article is about stuff.
3403
- --
3404
-
3405
- == Section One
3406
-
3407
- content
3408
- EOS
3409
-
3410
- output = convert_string input
3411
- assert_css '.quoteblock', output, 1
3412
- assert_css '.quoteblock.abstract', output, 1
3413
- assert_css '#preamble .quoteblock', output, 1
3414
- assert_css '.quoteblock > .title', output, 1
3415
- assert_css '.quoteblock > .title + blockquote', output, 1
3416
- assert_css '.quoteblock > .title + blockquote > .paragraph', output, 1
3417
- end
3418
-
3419
- test 'should allow abstract in document with title if doctype is book' do
3420
- input = <<-EOS
3421
- = Book
3422
- :doctype: book
3423
-
3424
- [abstract]
3425
- Abstract for book with title is valid
3426
- EOS
3427
-
3428
- output = convert_string input
3429
- assert_css '.abstract', output, 1
3430
- end
3431
-
3432
- test 'should not allow abstract as direct child of document if doctype is book' do
3433
- input = <<-EOS
3434
- :doctype: book
3435
-
3436
- [abstract]
3437
- Abstract for book without title is invalid.
3438
- EOS
3439
-
3440
- output = convert_string input
3441
- assert_css '.abstract', output, 0
3442
- assert_message @logger, :WARN, 'abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
3443
- end
3444
-
3445
- test 'should make abstract on open block without title converted to DocBook' do
3446
- input = <<-EOS
3447
- = Article
3448
-
3449
- [abstract]
3450
- --
3451
- This article is about stuff.
3452
-
3453
- And other stuff.
3454
- --
3455
- EOS
3456
-
3457
- output = convert_string input, :backend => 'docbook'
3458
- assert_css 'abstract', output, 1
3459
- assert_css 'abstract > simpara', output, 2
3460
- end
3461
-
3462
- test 'should make abstract on open block with title converted to DocBook' do
3463
- input = <<-EOS
3464
- = Article
3465
-
3466
- .My abstract
3467
- [abstract]
3468
- --
3469
- This article is about stuff.
3470
- --
3471
- EOS
3472
-
3473
- output = convert_string input, :backend => 'docbook'
3474
- assert_css 'abstract', output, 1
3475
- assert_css 'abstract > title', output, 1
3476
- assert_css 'abstract > title + simpara', output, 1
3477
- end
3478
-
3479
- test 'should allow abstract in document with title if doctype is book converted to DocBook' do
3480
- input = <<-EOS
3481
- = Book
3482
- :doctype: book
3483
-
3484
- [abstract]
3485
- Abstract for book with title is valid
3486
- EOS
3487
-
3488
- output = convert_string input, :backend => 'docbook'
3489
- assert_css 'abstract', output, 1
3490
- end
3491
-
3492
- test 'should not allow abstract as direct child of document if doctype is book converted to DocBook' do
3493
- input = <<-EOS
3494
- :doctype: book
3495
-
3496
- [abstract]
3497
- Abstract for book is invalid.
3498
- EOS
3499
-
3500
- output = convert_string input, :backend => 'docbook'
3501
- assert_css 'abstract', output, 0
3502
- assert_message @logger, :WARN, 'abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
3503
- end
3504
-
3505
- # TODO partintro shouldn't be recognized if doctype is not book, should be in proper place
3506
- test 'should accept partintro on open block without title' do
3507
- input = <<-EOS
3508
- = Book
3509
- :doctype: book
3510
-
3511
- = Part 1
3512
-
3513
- [partintro]
3514
- --
3515
- This is a part intro.
3516
-
3517
- It can have multiple paragraphs.
3518
- --
3519
-
3520
- == Chapter 1
3521
-
3522
- content
3523
- EOS
3524
-
3525
- output = convert_string input
3526
- assert_css '.openblock', output, 1
3527
- assert_css '.openblock.partintro', output, 1
3528
- assert_css '.openblock .title', output, 0
3529
- assert_css '.openblock .content', output, 1
3530
- assert_xpath %(//h1[@id="_part_1"]/following-sibling::*[#{contains_class(:openblock)}]), output, 1
3531
- assert_xpath %(//*[#{contains_class(:openblock)}]/*[@class="content"]/*[@class="paragraph"]), output, 2
3532
- end
3533
-
3534
- test 'should accept partintro on open block with title' do
3535
- input = <<-EOS
3536
- = Book
3537
- :doctype: book
3538
-
3539
- = Part 1
3540
-
3541
- .Intro title
3542
- [partintro]
3543
- --
3544
- This is a part intro with a title.
3545
- --
3546
-
3547
- == Chapter 1
3548
-
3549
- content
3550
- EOS
3551
-
3552
- output = convert_string input
3553
- assert_css '.openblock', output, 1
3554
- assert_css '.openblock.partintro', output, 1
3555
- assert_css '.openblock .title', output, 1
3556
- assert_css '.openblock .content', output, 1
3557
- assert_xpath %(//h1[@id="_part_1"]/following-sibling::*[#{contains_class(:openblock)}]), output, 1
3558
- assert_xpath %(//*[#{contains_class(:openblock)}]/*[@class="title"][text() = "Intro title"]), output, 1
3559
- assert_xpath %(//*[#{contains_class(:openblock)}]/*[@class="content"]/*[@class="paragraph"]), output, 1
3560
- end
3561
-
3562
- test 'should exclude partintro if not a child of part' do
3563
- input = <<-EOS
3564
- = Book
3565
- :doctype: book
3566
-
3567
- [partintro]
3568
- part intro paragraph
3569
- EOS
3570
-
3571
- output = convert_string input
3572
- assert_css '.partintro', output, 0
3573
- assert_message @logger, :ERROR, 'partintro block can only be used when doctype is book and must be a child of a book part. Excluding block content.'
3574
- end
3575
-
3576
- test 'should not allow partintro unless doctype is book' do
3577
- input = <<-EOS
3578
- [partintro]
3579
- part intro paragraph
3580
- EOS
3581
-
3582
- output = convert_string input
3583
- assert_css '.partintro', output, 0
3584
- assert_message @logger, :ERROR, 'partintro block can only be used when doctype is book and must be a child of a book part. Excluding block content.'
3585
- end
3586
-
3587
- test 'should accept partintro on open block without title converted to DocBook' do
3588
- input = <<-EOS
3589
- = Book
3590
- :doctype: book
3591
-
3592
- = Part 1
3593
-
3594
- [partintro]
3595
- --
3596
- This is a part intro.
3597
-
3598
- It can have multiple paragraphs.
3599
- --
3600
-
3601
- == Chapter 1
3602
-
3603
- content
3604
- EOS
3605
-
3606
- output = convert_string input, :backend => 'docbook45'
3607
- assert_css 'partintro', output, 1
3608
- assert_css 'part#_part_1 > partintro', output, 1
3609
- assert_css 'partintro > simpara', output, 2
3610
- end
3611
-
3612
- test 'should accept partintro on open block with title converted to DocBook' do
3613
- input = <<-EOS
3614
- = Book
3615
- :doctype: book
3616
-
3617
- = Part 1
3618
-
3619
- .Intro title
3620
- [partintro]
3621
- --
3622
- This is a part intro with a title.
3623
- --
3624
-
3625
- == Chapter 1
3626
-
3627
- content
3628
- EOS
3629
-
3630
- output = convert_string input, :backend => 'docbook45'
3631
- assert_css 'partintro', output, 1
3632
- assert_css 'part#_part_1 > partintro', output, 1
3633
- assert_css 'partintro > title', output, 1
3634
- assert_css 'partintro > title + simpara', output, 1
3635
- end
3636
-
3637
- test 'should exclude partintro if not a child of part converted to DocBook' do
3638
- input = <<-EOS
3639
- = Book
3640
- :doctype: book
3641
-
3642
- [partintro]
3643
- part intro paragraph
3644
- EOS
3645
-
3646
- output = convert_string input, :backend => 'docbook'
3647
- assert_css 'partintro', output, 0
3648
- assert_message @logger, :ERROR, 'partintro block can only be used when doctype is book and must be a child of a book part. Excluding block content.'
3649
- end
3650
-
3651
- test 'should not allow partintro unless doctype is book converted to DocBook' do
3652
- input = <<-EOS
3653
- [partintro]
3654
- part intro paragraph
3655
- EOS
3656
-
3657
- output = convert_string input, :backend => 'docbook'
3658
- assert_css 'partintro', output, 0
3659
- assert_message @logger, :ERROR, 'partintro block can only be used when doctype is book and must be a child of a book part. Excluding block content.'
3660
- end
3661
- end
3662
-
3663
- context 'Substitutions' do
3664
- test 'processor should not crash if subs are empty' do
3665
- input = <<-EOS
3666
- [subs=","]
3667
- ....
3668
- content
3669
- ....
3670
- EOS
3671
-
3672
- doc = document_from_string input
3673
- block = doc.blocks.first
3674
- assert_equal [], block.subs
3675
- end
3676
-
3677
- test 'should be able to append subs to default block substitution list' do
3678
- input = <<-EOS
3679
- :application: Asciidoctor
3680
-
3681
- [subs="+attributes,+macros"]
3682
- ....
3683
- {application}
3684
- ....
3685
- EOS
3686
-
3687
- doc = document_from_string input
3688
- block = doc.blocks.first
3689
- assert_equal [:specialcharacters, :attributes, :macros], block.subs
3690
- end
3691
-
3692
- test 'should be able to prepend subs to default block substitution list' do
3693
- input = <<-EOS
3694
- :application: Asciidoctor
3695
-
3696
- [subs="attributes+"]
3697
- ....
3698
- {application}
3699
- ....
3700
- EOS
3701
-
3702
- doc = document_from_string input
3703
- block = doc.blocks.first
3704
- assert_equal [:attributes, :specialcharacters], block.subs
3705
- end
3706
-
3707
- test 'should be able to remove subs to default block substitution list' do
3708
- input = <<-EOS
3709
- [subs="-quotes,-replacements"]
3710
- content
3711
- EOS
3712
-
3713
- doc = document_from_string input
3714
- block = doc.blocks.first
3715
- assert_equal [:specialcharacters, :attributes, :macros, :post_replacements], block.subs
3716
- end
3717
-
3718
- test 'should be able to prepend, append and remove subs from default block substitution list' do
3719
- input = <<-EOS
3720
- :application: asciidoctor
3721
-
3722
- [subs="attributes+,-verbatim,+specialcharacters,+macros"]
3723
- ....
3724
- https://{application}.org[{gt}{gt}] <1>
3725
- ....
3726
- EOS
3727
-
3728
- doc = document_from_string input, :header_footer => false
3729
- block = doc.blocks.first
3730
- assert_equal [:attributes, :specialcharacters, :macros], block.subs
3731
- result = doc.convert
3732
- assert_includes result, '<pre><a href="https://asciidoctor.org">&gt;&gt;</a> &lt;1&gt;</pre>'
3733
- end
3734
-
3735
- test 'should be able to set subs then modify them' do
3736
- input = <<-EOS
3737
- [subs="verbatim,-callouts"]
3738
- _hey now_ <1>
3739
- EOS
3740
-
3741
- doc = document_from_string input, :header_footer => false
3742
- block = doc.blocks.first
3743
- assert_equal [:specialcharacters], block.subs
3744
- result = doc.convert
3745
- assert_includes result, '_hey now_ &lt;1&gt;'
3746
- end
3747
- end
3748
-
3749
- context 'References' do
3750
- test 'should not recognize block anchor with illegal id characters' do
3751
- input = <<-EOS
3752
- [[illegal$id,Reference Text]]
3753
- ----
3754
- content
3755
- ----
3756
- EOS
3757
-
3758
- doc = document_from_string input
3759
- block = doc.blocks.first
3760
- assert_nil block.id
3761
- assert_nil(block.attr 'reftext')
3762
- refute doc.catalog[:ids].has_key?('illegal$id')
3763
- end
3764
-
3765
- test 'should not recognize block anchor that starts with digit' do
3766
- input = <<-EOS
3767
- [[3-blind-mice]]
3768
- --
3769
- see how they run
3770
- --
3771
- EOS
3772
-
3773
- output = convert_string_to_embedded input
3774
- assert_includes output, '[[3-blind-mice]]'
3775
- assert_xpath '/*[@id = ":3-blind-mice"]', output, 0
3776
- end
3777
-
3778
- test 'should recognize block anchor that starts with colon' do
3779
- input = <<-EOS
3780
- [[:idname]]
3781
- --
3782
- content
3783
- --
3784
- EOS
3785
-
3786
- output = convert_string_to_embedded input
3787
- assert_xpath '/*[@id = ":idname"]', output, 1
3788
- end
3789
-
3790
- test 'should use specified id and reftext when registering block reference' do
3791
- input = <<-EOS
3792
- [[debian,Debian Install]]
3793
- .Installation on Debian
3794
- ----
3795
- $ apt-get install asciidoctor
3796
- ----
3797
- EOS
3798
-
3799
- doc = document_from_string input
3800
- reftext = doc.catalog[:ids]['debian']
3801
- refute_nil reftext
3802
- assert_equal 'Debian Install', reftext
3803
- end
3804
-
3805
- test 'should allow square brackets in block reference text' do
3806
- input = <<-EOS
3807
- [[debian,[Debian] Install]]
3808
- .Installation on Debian
3809
- ----
3810
- $ apt-get install asciidoctor
3811
- ----
3812
- EOS
3813
-
3814
- doc = document_from_string input
3815
- reftext = doc.catalog[:ids]['debian']
3816
- refute_nil reftext
3817
- assert_equal '[Debian] Install', reftext
3818
- end
3819
-
3820
- test 'should allow comma in block reference text' do
3821
- input = <<-EOS
3822
- [[debian, Debian, Ubuntu]]
3823
- .Installation on Debian
3824
- ----
3825
- $ apt-get install asciidoctor
3826
- ----
3827
- EOS
3828
-
3829
- doc = document_from_string input
3830
- reftext = doc.catalog[:ids]['debian']
3831
- refute_nil reftext
3832
- assert_equal 'Debian, Ubuntu', reftext
3833
- end
3834
-
3835
- test 'should substitute attribute references in reftext when registering block reference' do
3836
- input = <<-EOS
3837
- :label-tiger: Tiger
3838
-
3839
- [[tiger-evolution,Evolution of the {label-tiger}]]
3840
- ****
3841
- Information about the evolution of the tiger.
3842
- ****
3843
- EOS
3844
-
3845
- doc = document_from_string input
3846
- reftext = doc.catalog[:ids]['tiger-evolution']
3847
- refute_nil reftext
3848
- assert_equal 'Evolution of the Tiger', reftext
3849
- ref = doc.catalog[:refs]['tiger-evolution']
3850
- refute_nil ref
3851
- assert_equal 'Evolution of the Tiger', ref.attributes['reftext']
3852
- end
3853
-
3854
- test 'should use specified reftext when registering block reference' do
3855
- input = <<-EOS
3856
- [[debian]]
3857
- [reftext="Debian Install"]
3858
- .Installation on Debian
3859
- ----
3860
- $ apt-get install asciidoctor
3861
- ----
3862
- EOS
3863
-
3864
- doc = document_from_string input
3865
- reftext = doc.catalog[:ids]['debian']
3866
- refute_nil reftext
3867
- assert_equal 'Debian Install', reftext
3868
- end
3869
- end
3870
- end