asciidoctor 1.5.6.2 → 1.5.7

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

Potentially problematic release.


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

Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +330 -143
  3. data/README-fr.adoc +441 -0
  4. data/README-jp.adoc +418 -0
  5. data/README-zh_CN.adoc +430 -0
  6. data/README.adoc +454 -0
  7. data/Rakefile +57 -0
  8. data/asciidoctor.gemspec +7 -1
  9. data/data/locale/attributes-ar.adoc +22 -0
  10. data/data/locale/attributes-bg.adoc +22 -0
  11. data/data/locale/attributes-ca.adoc +22 -0
  12. data/data/locale/attributes-cs.adoc +22 -0
  13. data/data/locale/attributes-da.adoc +22 -0
  14. data/data/locale/attributes-de.adoc +22 -0
  15. data/data/locale/attributes-en.adoc +23 -0
  16. data/data/locale/attributes-es.adoc +22 -0
  17. data/data/locale/attributes-fa.adoc +22 -0
  18. data/data/locale/attributes-fi.adoc +22 -0
  19. data/data/locale/attributes-fr.adoc +22 -0
  20. data/data/locale/attributes-hu.adoc +22 -0
  21. data/data/locale/attributes-id.adoc +22 -0
  22. data/data/locale/attributes-it.adoc +22 -0
  23. data/data/locale/attributes-ja.adoc +22 -0
  24. data/data/locale/attributes-kr.adoc +22 -0
  25. data/data/locale/attributes-nb.adoc +22 -0
  26. data/data/locale/attributes-nl.adoc +22 -0
  27. data/data/locale/attributes-nn.adoc +22 -0
  28. data/data/locale/attributes-pl.adoc +22 -0
  29. data/data/locale/attributes-pt.adoc +22 -0
  30. data/data/locale/attributes-pt_BR.adoc +22 -0
  31. data/data/locale/attributes-ro.adoc +22 -0
  32. data/data/locale/attributes-ru.adoc +22 -0
  33. data/data/locale/attributes-sr.adoc +22 -0
  34. data/data/locale/attributes-sr_Latn.adoc +22 -0
  35. data/data/locale/attributes-tr.adoc +22 -0
  36. data/data/locale/attributes-uk.adoc +22 -0
  37. data/data/locale/attributes-zh_CN.adoc +22 -0
  38. data/data/locale/attributes-zh_TW.adoc +22 -0
  39. data/data/locale/attributes.adoc +8 -649
  40. data/data/stylesheets/asciidoctor-default.css +77 -72
  41. data/features/xref.feature +366 -7
  42. data/lib/asciidoctor.rb +107 -93
  43. data/lib/asciidoctor/abstract_block.rb +247 -239
  44. data/lib/asciidoctor/abstract_node.rb +56 -58
  45. data/lib/asciidoctor/block.rb +3 -3
  46. data/lib/asciidoctor/callouts.rb +1 -1
  47. data/lib/asciidoctor/cli/invoker.rb +36 -9
  48. data/lib/asciidoctor/cli/options.rb +63 -25
  49. data/lib/asciidoctor/converter.rb +23 -13
  50. data/lib/asciidoctor/converter/base.rb +4 -0
  51. data/lib/asciidoctor/converter/docbook45.rb +16 -9
  52. data/lib/asciidoctor/converter/docbook5.rb +115 -97
  53. data/lib/asciidoctor/converter/factory.rb +29 -31
  54. data/lib/asciidoctor/converter/html5.rb +229 -192
  55. data/lib/asciidoctor/converter/manpage.rb +72 -50
  56. data/lib/asciidoctor/converter/template.rb +12 -12
  57. data/lib/asciidoctor/core_ext.rb +5 -1
  58. data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +6 -0
  59. data/lib/asciidoctor/document.rb +168 -77
  60. data/lib/asciidoctor/extensions.rb +79 -47
  61. data/lib/asciidoctor/helpers.rb +33 -11
  62. data/lib/asciidoctor/inline.rb +3 -2
  63. data/lib/asciidoctor/list.rb +2 -1
  64. data/lib/asciidoctor/logging.rb +122 -0
  65. data/lib/asciidoctor/parser.rb +406 -382
  66. data/lib/asciidoctor/path_resolver.rb +169 -162
  67. data/lib/asciidoctor/reader.rb +166 -121
  68. data/lib/asciidoctor/section.rb +45 -28
  69. data/lib/asciidoctor/stylesheets.rb +13 -5
  70. data/lib/asciidoctor/substitutors.rb +328 -254
  71. data/lib/asciidoctor/table.rb +105 -48
  72. data/lib/asciidoctor/timings.rb +34 -6
  73. data/lib/asciidoctor/version.rb +1 -1
  74. data/man/asciidoctor.1 +41 -23
  75. data/man/asciidoctor.adoc +14 -8
  76. data/test/api_test.rb +1004 -0
  77. data/test/attributes_test.rb +241 -50
  78. data/test/blocks_test.rb +549 -124
  79. data/test/converter_test.rb +170 -78
  80. data/test/document_test.rb +208 -767
  81. data/test/extensions_test.rb +188 -53
  82. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +1 -1
  83. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +1 -1
  84. data/test/fixtures/file-with-missing-include.adoc +1 -0
  85. data/test/fixtures/include-file.jsx +8 -0
  86. data/test/fixtures/lists.adoc +96 -0
  87. data/test/fixtures/other-chapters.adoc +11 -0
  88. data/test/fixtures/outer-include.adoc +5 -0
  89. data/test/fixtures/sample.asciidoc +5 -1
  90. data/test/fixtures/subdir/index.adoc +3 -0
  91. data/test/fixtures/subdir/inner-include.adoc +3 -0
  92. data/test/fixtures/subdir/middle-include.adoc +5 -0
  93. data/test/fixtures/tagged-class-enclosed.rb +0 -1
  94. data/test/fixtures/unclosed-tag.adoc +3 -0
  95. data/test/fixtures/unexpected-end-tag.adoc +4 -0
  96. data/test/invoker_test.rb +101 -40
  97. data/test/links_test.rb +266 -72
  98. data/test/lists_test.rb +243 -45
  99. data/test/logger_test.rb +211 -0
  100. data/test/manpage_test.rb +124 -6
  101. data/test/options_test.rb +46 -1
  102. data/test/paragraphs_test.rb +23 -10
  103. data/test/parser_test.rb +30 -1
  104. data/test/paths_test.rb +115 -33
  105. data/test/preamble_test.rb +1 -1
  106. data/test/reader_test.rb +337 -81
  107. data/test/sections_test.rb +656 -72
  108. data/test/substitutions_test.rb +182 -57
  109. data/test/tables_test.rb +324 -57
  110. data/test/test_helper.rb +77 -32
  111. data/test/text_test.rb +7 -7
  112. metadata +67 -3
@@ -4,7 +4,17 @@ unless defined? ASCIIDOCTOR_PROJECT_DIR
4
4
  require 'test_helper'
5
5
  end
6
6
 
7
- context "Blocks" do
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
+
8
18
  context 'Layout Breaks' do
9
19
  test 'horizontal rule' do
10
20
  %w(''' '''' '''''').each do |line|
@@ -141,7 +151,7 @@ block comment
141
151
  EOS
142
152
  d = document_from_string input
143
153
  assert_equal 1, d.blocks.size
144
- assert_xpath '//p', d.render, 1
154
+ assert_xpath '//p', d.convert, 1
145
155
  end
146
156
 
147
157
  test 'line starting with three slashes should not be line comment' do
@@ -181,6 +191,36 @@ line should be rendered
181
191
  assert_xpath '//p[text() = "line should be rendered"]', output, 1
182
192
  end
183
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
+ render_embedded_string 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
+ render_embedded_string input
221
+ assert_message @logger, :WARN, '<stdin>: line 4: unterminated comment block', Hash
222
+ end
223
+
184
224
  # WARNING if first line of content is a directive, it will get interpretted before we know it's a comment block
185
225
  # it happens because we always look a line ahead...not sure what we can do about it
186
226
  test 'preprocessor directives should not be processed within comment open block' do
@@ -311,15 +351,30 @@ ____
311
351
 
312
352
  test 'quote block with attribute and id and role shorthand' do
313
353
  input = <<-EOS
314
- [quote#think.big, Donald Trump]
354
+ [quote#justice-to-all.solidarity, Martin Luther King, Jr.]
315
355
  ____
316
- As long as your going to be thinking anyway, think big.
356
+ Injustice anywhere is a threat to justice everywhere.
317
357
  ____
318
358
  EOS
319
359
 
320
360
  output = render_embedded_string input
321
361
  assert_css '.quoteblock', output, 1
322
- assert_css '#think.quoteblock.big', 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 = render_embedded_string input
376
+ assert_css '.quoteblock', output, 1
377
+ assert_css '#justice-to-all.quoteblock.solidarity', output, 1
323
378
  assert_css '.quoteblock > .attribution', output, 1
324
379
  end
325
380
 
@@ -338,6 +393,42 @@ ____
338
393
  assert_css '.quoteblock > blockquote > .paragraph + .admonitionblock', output, 1
339
394
  end
340
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 = render_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 = render_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
+
341
432
  test 'quote block using air quotes with no attribution' do
342
433
  input = <<-EOS
343
434
  ""
@@ -429,6 +520,18 @@ Some more inspiring words.
429
520
  assert_equal "#{decode_char 8212} Famous Person", author.text.strip
430
521
  end
431
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 = render_embedded_string 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
+
432
535
  test 'quoted paragraph-style quote block with attribution' do
433
536
  input = <<-EOS
434
537
  "A famous quote.
@@ -448,6 +551,18 @@ Some more inspiring words."
448
551
  assert_equal "#{decode_char 8212} Famous Person", author.text.strip
449
552
  end
450
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 = render_embedded_string 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
+
451
566
  test 'single-line verse block without attribution' do
452
567
  input = <<-EOS
453
568
  [verse]
@@ -483,6 +598,44 @@ ____
483
598
  assert_equal "#{decode_char 8212} Famous Poet", author.text.strip
484
599
  end
485
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 = render_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 = render_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
+
486
639
  test 'multi-stanza verse block' do
487
640
  input = <<-EOS
488
641
  [verse]
@@ -539,9 +692,9 @@ ____
539
692
  <1> Not pointing to a callout
540
693
  EOS
541
694
 
542
- output, warnings = redirect_streams {|_, err| [(render_embedded_string input), err.string] }
695
+ output = render_embedded_string input
543
696
  assert_xpath '//pre[text()="La la la <1>"]', output, 1
544
- assert_includes warnings, 'line 5: no callouts refer to list item 1'
697
+ assert_message @logger, :WARN, '<stdin>: line 5: no callout found for <1>', Hash
545
698
  end
546
699
 
547
700
  test 'should perform normal subs on a verse block' do
@@ -553,7 +706,7 @@ ____
553
706
  EOS
554
707
 
555
708
  output = render_embedded_string input
556
- assert output.include?('<pre class="content"><em>GET /groups/<a href="#group-id">{group-id}</a></em></pre>')
709
+ assert_includes output, '<pre class="content"><em>GET /groups/<a href="#group-id">{group-id}</a></em></pre>'
557
710
  end
558
711
  end
559
712
 
@@ -591,7 +744,7 @@ You futz with XML.
591
744
  doc = document_from_string input
592
745
  assert_equal 1, doc.blocks[0].number
593
746
  assert_equal 2, doc.blocks[1].number
594
- output = doc.render
747
+ output = doc.convert
595
748
  assert_xpath '(//*[@class="exampleblock"])[1]/*[@class="title"][text()="Example 1. Writing Docs with AsciiDoc"]', output, 1
596
749
  assert_xpath '(//*[@class="exampleblock"])[2]/*[@class="title"][text()="Example 2. Writing Docs with DocBook"]', output, 1
597
750
  assert_equal 2, doc.attributes['example-number']
@@ -619,7 +772,7 @@ You futz with XML.
619
772
  doc = document_from_string input
620
773
  assert_equal 'A', doc.blocks[0].number
621
774
  assert_equal 'B', doc.blocks[1].number
622
- output = doc.render
775
+ output = doc.convert
623
776
  assert_xpath '(//*[@class="exampleblock"])[1]/*[@class="title"][text()="Example A. Writing Docs with AsciiDoc"]', output, 1
624
777
  assert_xpath '(//*[@class="exampleblock"])[2]/*[@class="title"][text()="Example B. Writing Docs with DocBook"]', output, 1
625
778
  assert_equal 'B', doc.attributes['example-number']
@@ -638,7 +791,7 @@ You just write.
638
791
 
639
792
  doc = document_from_string input
640
793
  assert_nil doc.blocks[0].number
641
- output = doc.render
794
+ output = doc.convert
642
795
  assert_xpath '(//*[@class="exampleblock"])[1]/*[@class="title"][text()="Look! Writing Docs with AsciiDoc"]', output, 1
643
796
  refute doc.attributes.has_key?('example-number')
644
797
  end
@@ -672,41 +825,58 @@ yet another example
672
825
  assert_xpath '(/*[@class="exampleblock"])[2]/*[@class="title"][text()="second example"]', output, 1
673
826
  assert_xpath '(/*[@class="exampleblock"])[3]/*[@class="title"][starts-with(text(), "Exhibit ")]', output, 1
674
827
  end
828
+
829
+ test 'should warn if example block is not terminated' do
830
+ input = <<-EOS
831
+ outside
832
+
833
+ ====
834
+ inside
835
+
836
+ still inside
837
+
838
+ eof
839
+ EOS
840
+
841
+ output = render_embedded_string input
842
+ assert_xpath '/*[@class="exampleblock"]', output, 1
843
+ assert_message @logger, :WARN, '<stdin>: line 3: unterminated example block', Hash
844
+ end
675
845
  end
676
846
 
677
847
  context 'Admonition Blocks' do
678
848
  test 'caption block-level attribute should be used as caption' do
679
- input = <<-EOS
849
+ input = <<-EOS
680
850
  :tip-caption: Pro Tip
681
851
 
682
852
  [caption="Pro Tip"]
683
853
  TIP: Override the caption of an admonition block using an attribute entry
684
- EOS
854
+ EOS
685
855
 
686
- output = render_embedded_string input
687
- assert_xpath '/*[@class="admonitionblock tip"]//*[@class="icon"]/*[@class="title"][text()="Pro Tip"]', output, 1
856
+ output = render_embedded_string input
857
+ assert_xpath '/*[@class="admonitionblock tip"]//*[@class="icon"]/*[@class="title"][text()="Pro Tip"]', output, 1
688
858
  end
689
859
 
690
860
  test 'can override caption of admonition block using document attribute' do
691
- input = <<-EOS
861
+ input = <<-EOS
692
862
  :tip-caption: Pro Tip
693
863
 
694
864
  TIP: Override the caption of an admonition block using an attribute entry
695
- EOS
865
+ EOS
696
866
 
697
- output = render_embedded_string input
698
- assert_xpath '/*[@class="admonitionblock tip"]//*[@class="icon"]/*[@class="title"][text()="Pro Tip"]', output, 1
867
+ output = render_embedded_string input
868
+ assert_xpath '/*[@class="admonitionblock tip"]//*[@class="icon"]/*[@class="title"][text()="Pro Tip"]', output, 1
699
869
  end
700
870
 
701
871
  test 'blank caption document attribute should not blank admonition block caption' do
702
- input = <<-EOS
872
+ input = <<-EOS
703
873
  :caption:
704
874
 
705
875
  TIP: Override the caption of an admonition block using an attribute entry
706
- EOS
876
+ EOS
707
877
 
708
- output = render_embedded_string input
709
- assert_xpath '/*[@class="admonitionblock tip"]//*[@class="icon"]/*[@class="title"][text()="Tip"]', output, 1
878
+ output = render_embedded_string input
879
+ assert_xpath '/*[@class="admonitionblock tip"]//*[@class="icon"]/*[@class="title"][text()="Tip"]', output, 1
710
880
  end
711
881
  end
712
882
 
@@ -820,7 +990,7 @@ last line
820
990
  doc = document_from_string input, :header_footer => false
821
991
  block = doc.blocks.first
822
992
  assert_equal ['', '', ' first line', '', 'last line', '', '{empty}', ''], block.lines
823
- result = doc.render
993
+ result = doc.convert
824
994
  assert_xpath %(//pre[text()=" first line\n\nlast line"]), result, 1
825
995
  end
826
996
 
@@ -1014,8 +1184,8 @@ Map<String, String> *attributes*; //<1>
1014
1184
 
1015
1185
  block = block_from_string input
1016
1186
  assert_equal [:specialcharacters,:callouts,:quotes], block.subs
1017
- output = block.render
1018
- assert output.include?('Map&lt;String, String&gt; <strong>attributes</strong>;')
1187
+ output = block.convert
1188
+ assert_includes output, 'Map&lt;String, String&gt; <strong>attributes</strong>;'
1019
1189
  assert_xpath '//pre/b[text()="(1)"]', output, 1
1020
1190
  end
1021
1191
 
@@ -1028,7 +1198,7 @@ No callout here <1>
1028
1198
  EOS
1029
1199
  block = block_from_string input
1030
1200
  assert_equal [:specialcharacters], block.subs
1031
- output = block.render
1201
+ output = block.convert
1032
1202
  assert_xpath '//pre/b[text()="(1)"]', output, 0
1033
1203
  end
1034
1204
 
@@ -1067,6 +1237,20 @@ AssertionError
1067
1237
  assert_equal output.rstrip, output2.rstrip
1068
1238
  end
1069
1239
 
1240
+ test 'first character of block title may be a period if not followed by space' do
1241
+ input = <<-EOS
1242
+ ..gitignore
1243
+ ----
1244
+ /.bundle/
1245
+ /build/
1246
+ /Gemfile.lock
1247
+ ----
1248
+ EOS
1249
+
1250
+ output = render_embedded_string input
1251
+ assert_xpath '//*[@class="title"][text()=".gitignore"]', output
1252
+ end
1253
+
1070
1254
  test 'listing block without title should generate screen element in docbook' do
1071
1255
  input = <<-EOS
1072
1256
  ----
@@ -1151,6 +1335,111 @@ ____
1151
1335
  assert_xpath '//*[@class="openblock"]//p', output, 3
1152
1336
  assert_xpath '//*[@class="openblock"]//*[@class="quoteblock"]', output, 1
1153
1337
  end
1338
+
1339
+ test 'should transfer id and reftext on open block to DocBook output' do
1340
+ input = <<-EOS
1341
+ Check out that <<open>>!
1342
+
1343
+ [[open,Open Block]]
1344
+ --
1345
+ This is an open block.
1346
+
1347
+ TIP: An open block can have other blocks inside of it.
1348
+ --
1349
+
1350
+ Back to our regularly scheduled programming.
1351
+ EOS
1352
+
1353
+ output = render_string input, :backend => :docbook, :keep_namespaces => true
1354
+ assert_css 'article > simpara', output, 2
1355
+ assert_css 'article > para', output, 1
1356
+ assert_css 'article > para > simpara', output, 1
1357
+ assert_css 'article > para > tip', output, 1
1358
+ open = xmlnodes_at_xpath '/xmlns:article/xmlns:para', output, 1
1359
+ # nokogiri can't make up its mind
1360
+ id = open.attribute('id') || open.attribute('xml:id')
1361
+ refute_nil id
1362
+ assert_equal 'open', id.value
1363
+ xreflabel = open.attribute('xreflabel')
1364
+ refute_nil xreflabel
1365
+ assert_equal 'Open Block', xreflabel.value
1366
+ end
1367
+
1368
+ test 'should transfer id and reftext on open paragraph to DocBook output' do
1369
+ input = <<-EOS
1370
+ [open#openpara,reftext="Open Paragraph"]
1371
+ This is an open paragraph.
1372
+ EOS
1373
+
1374
+ output = render_string input, :backend => :docbook, :keep_namespaces => true
1375
+ assert_css 'article > simpara', output, 1
1376
+ open = xmlnodes_at_xpath '/xmlns:article/xmlns:simpara', output, 1
1377
+ open = xmlnodes_at_xpath '/xmlns:article/xmlns:simpara[text()="This is an open paragraph."]', output, 1
1378
+ # nokogiri can't make up its mind
1379
+ id = open.attribute('id') || open.attribute('xml:id')
1380
+ refute_nil id
1381
+ assert_equal 'openpara', id.value
1382
+ xreflabel = open.attribute('xreflabel')
1383
+ refute_nil xreflabel
1384
+ assert_equal 'Open Paragraph', xreflabel.value
1385
+ end
1386
+
1387
+ test 'should transfer title on open block to DocBook output' do
1388
+ input = <<-EOS
1389
+ .Behold the open
1390
+ --
1391
+ This is an open block with a title.
1392
+ --
1393
+ EOS
1394
+
1395
+ output = render_string input, :backend => :docbook
1396
+ assert_css 'article > formalpara', output, 1
1397
+ assert_css 'article > formalpara > *', output, 2
1398
+ assert_css 'article > formalpara > title', output, 1
1399
+ assert_xpath '/article/formalpara/title[text()="Behold the open"]', output, 1
1400
+ assert_css 'article > formalpara > para', output, 1
1401
+ assert_css 'article > formalpara > para > simpara', output, 1
1402
+ end
1403
+
1404
+ test 'should transfer title on open paragraph to DocBook output' do
1405
+ input = <<-EOS
1406
+ .Behold the open
1407
+ This is an open paragraph with a title.
1408
+ EOS
1409
+
1410
+ output = render_string input, :backend => :docbook
1411
+ assert_css 'article > formalpara', output, 1
1412
+ assert_css 'article > formalpara > *', output, 2
1413
+ assert_css 'article > formalpara > title', output, 1
1414
+ assert_xpath '/article/formalpara/title[text()="Behold the open"]', output, 1
1415
+ assert_css 'article > formalpara > para', output, 1
1416
+ assert_css 'article > formalpara > para[text()="This is an open paragraph with a title."]', output, 1
1417
+ end
1418
+
1419
+ test 'should transfer role on open block to DocBook output' do
1420
+ input = <<-EOS
1421
+ [.container]
1422
+ --
1423
+ This is an open block.
1424
+ It holds stuff.
1425
+ --
1426
+ EOS
1427
+
1428
+ output = render_string input, :backend => :docbook
1429
+ assert_css 'article > para[role=container]', output, 1
1430
+ assert_css 'article > para[role=container] > simpara', output, 1
1431
+ end
1432
+
1433
+ test 'should transfer role on open paragraph to DocBook output' do
1434
+ input = <<-EOS
1435
+ [.container]
1436
+ This is an open block.
1437
+ It holds stuff.
1438
+ EOS
1439
+
1440
+ output = render_string input, :backend => :docbook
1441
+ assert_css 'article > simpara[role=container]', output, 1
1442
+ end
1154
1443
  end
1155
1444
 
1156
1445
  context 'Passthrough Blocks' do
@@ -1240,7 +1529,7 @@ line below
1240
1529
  doc = document_from_string input, :header_footer => false
1241
1530
  block = doc.blocks[1]
1242
1531
  assert_equal ['', '', ' first line', '', 'last line', '', ''], block.lines
1243
- result = doc.render
1532
+ result = doc.convert
1244
1533
  assert_equal "line above\n first line\n\nlast line\nline below", result, 1
1245
1534
  end
1246
1535
  end
@@ -1293,6 +1582,88 @@ line below
1293
1582
  assert_equal expect.strip, output.strip
1294
1583
  end
1295
1584
 
1585
+ test 'should not split equation in AsciiMath block at single newline' do
1586
+ input = <<-'EOS'
1587
+ [asciimath]
1588
+ ++++
1589
+ f: bbb"N" -> bbb"N"
1590
+ f: x |-> x + 1
1591
+ ++++
1592
+ EOS
1593
+ expected = <<-'EOS'.chomp
1594
+ \$f: bbb"N" -&gt; bbb"N"
1595
+ f: x |-&gt; x + 1\$
1596
+ EOS
1597
+
1598
+ output = render_embedded_string input
1599
+ assert_css '.stemblock', output, 1
1600
+ nodes = xmlnodes_at_xpath '//*[@class="content"]', output
1601
+ assert_equal expected, nodes.first.inner_html.strip
1602
+ end
1603
+
1604
+ test 'should split equation in AsciiMath block at escaped newline' do
1605
+ input = <<-'EOS'
1606
+ [asciimath]
1607
+ ++++
1608
+ f: bbb"N" -> bbb"N" \
1609
+ f: x |-> x + 1
1610
+ ++++
1611
+ EOS
1612
+ expected = <<-'EOS'.chomp
1613
+ \$f: bbb"N" -&gt; bbb"N"\$<br>
1614
+ \$f: x |-&gt; x + 1\$
1615
+ EOS
1616
+
1617
+ output = render_embedded_string input
1618
+ assert_css '.stemblock', output, 1
1619
+ nodes = xmlnodes_at_xpath '//*[@class="content"]', output
1620
+ assert_equal expected, nodes.first.inner_html.strip
1621
+ end
1622
+
1623
+ test 'should split equation in AsciiMath block at sequence of escaped newlines' do
1624
+ input = <<-'EOS'
1625
+ [asciimath]
1626
+ ++++
1627
+ f: bbb"N" -> bbb"N" \
1628
+ \
1629
+ f: x |-> x + 1
1630
+ ++++
1631
+ EOS
1632
+ expected = <<-'EOS'.chomp
1633
+ \$f: bbb"N" -&gt; bbb"N"\$<br>
1634
+ <br>
1635
+ \$f: x |-&gt; x + 1\$
1636
+ EOS
1637
+
1638
+ output = render_embedded_string input
1639
+ assert_css '.stemblock', output, 1
1640
+ nodes = xmlnodes_at_xpath '//*[@class="content"]', output
1641
+ assert_equal expected, nodes.first.inner_html.strip
1642
+ end
1643
+
1644
+ test 'should split equation in AsciiMath block at newline sequence and preserve breaks' do
1645
+ input = <<-'EOS'
1646
+ [asciimath]
1647
+ ++++
1648
+ f: bbb"N" -> bbb"N"
1649
+
1650
+
1651
+ f: x |-> x + 1
1652
+ ++++
1653
+ EOS
1654
+ expected = <<-'EOS'.chomp
1655
+ \$f: bbb"N" -&gt; bbb"N"\$<br>
1656
+ <br>
1657
+ <br>
1658
+ \$f: x |-&gt; x + 1\$
1659
+ EOS
1660
+
1661
+ output = render_embedded_string input
1662
+ assert_css '.stemblock', output, 1
1663
+ nodes = xmlnodes_at_xpath '//*[@class="content"]', output
1664
+ assert_equal expected, nodes.first.inner_html.strip
1665
+ end
1666
+
1296
1667
  test 'should add AsciiMath delimiters around asciimath block content' do
1297
1668
  input = <<-'EOS'
1298
1669
  [asciimath]
@@ -1321,7 +1692,8 @@ sqrt(3x-1)+(1+x)^2 < y
1321
1692
  assert_equal '\$sqrt(3x-1)+(1+x)^2 &lt; y\$', nodes.first.to_s.strip
1322
1693
  end
1323
1694
 
1324
- test 'should render asciimath block in textobject of equation in DocBook backend' do
1695
+ test 'should convert contents of asciimath block to MathML in DocBook output if asciimath gem is available' do
1696
+ asciimath_available = !(Asciidoctor::Helpers.require_library 'asciimath', true, :ignore).nil?
1325
1697
  input = <<-'EOS'
1326
1698
  [asciimath]
1327
1699
  ++++
@@ -1333,8 +1705,17 @@ x+b/(2a)<+-sqrt((b^2)/(4a^2)-c/a)
1333
1705
  <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>
1334
1706
  </informalequation>)
1335
1707
 
1336
- output = render_embedded_string input, :backend => :docbook
1337
- assert_equal expect.strip, output.strip
1708
+ using_memory_logger do |logger|
1709
+ doc = document_from_string input, :backend => :docbook, :header_footer => false
1710
+ actual = doc.convert
1711
+ if asciimath_available
1712
+ assert_equal expect.strip, actual.strip
1713
+ assert_equal :loaded, doc.converter.instance_variable_get(:@asciimath)
1714
+ else
1715
+ assert_message logger, :WARN, 'optional gem \'asciimath\' is not installed. Functionality disabled.'
1716
+ assert_equal :unavailable, doc.converter.instance_variable_get(:@asciimath)
1717
+ end
1718
+ end
1338
1719
  end
1339
1720
 
1340
1721
  test 'should output title for latexmath block if defined' do
@@ -1371,7 +1752,7 @@ a//b
1371
1752
  assert_xpath '//*[@class="title"][text()="Simple fraction"]', output, 1
1372
1753
  end
1373
1754
 
1374
- test 'should add AsciiMath delimiters around stem block content if stem attribute != latexmath' do
1755
+ test 'should add AsciiMath delimiters around stem block content if stem attribute is asciimath, empty, or not set' do
1375
1756
  input = <<-'EOS'
1376
1757
  [stem]
1377
1758
  ++++
@@ -1382,7 +1763,8 @@ sqrt(3x-1)+(1+x)^2 < y
1382
1763
  [
1383
1764
  {},
1384
1765
  {'stem' => ''},
1385
- {'stem' => 'asciimath'}
1766
+ {'stem' => 'asciimath'},
1767
+ {'stem' => 'bogus'}
1386
1768
  ].each do |attributes|
1387
1769
  output = render_embedded_string input, :attributes => attributes
1388
1770
  assert_css '.stemblock', output, 1
@@ -1391,7 +1773,7 @@ sqrt(3x-1)+(1+x)^2 < y
1391
1773
  end
1392
1774
  end
1393
1775
 
1394
- test 'should add LaTeX math delimiters around stem block content if stem attribute is latexmath' do
1776
+ test 'should add LaTeX math delimiters around stem block content if stem attribute is latexmath, latex, or tex' do
1395
1777
  input = <<-'EOS'
1396
1778
  [stem]
1397
1779
  ++++
@@ -1399,10 +1781,36 @@ sqrt(3x-1)+(1+x)^2 < y
1399
1781
  ++++
1400
1782
  EOS
1401
1783
 
1402
- output = render_embedded_string input, :attributes => {'stem' => 'latexmath'}
1784
+ [
1785
+ {'stem' => 'latexmath'},
1786
+ {'stem' => 'latex'},
1787
+ {'stem' => 'tex'}
1788
+ ].each do |attributes|
1789
+ output = render_embedded_string input, :attributes => attributes
1790
+ assert_css '.stemblock', output, 1
1791
+ nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
1792
+ assert_equal '\[\sqrt{3x-1}+(1+x)^2 &lt; y\]', nodes.first.to_s.strip
1793
+ end
1794
+ end
1795
+
1796
+ test 'should allow stem style to be set using second positional argument of block attributes' do
1797
+ input = <<-EOS
1798
+ :stem: latexmath
1799
+
1800
+ [stem,asciimath]
1801
+ ++++
1802
+ sqrt(3x-1)+(1+x)^2 < y
1803
+ ++++
1804
+ EOS
1805
+
1806
+ doc = document_from_string input
1807
+ stemblock = doc.blocks[0]
1808
+ assert_equal :stem, stemblock.context
1809
+ assert_equal 'asciimath', stemblock.attributes['style']
1810
+ output = doc.convert :header_footer => false
1403
1811
  assert_css '.stemblock', output, 1
1404
1812
  nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
1405
- assert_equal '\[\sqrt{3x-1}+(1+x)^2 &lt; y\]', nodes.first.to_s.strip
1813
+ assert_equal '\$sqrt(3x-1)+(1+x)^2 &lt; y\$', nodes.first.to_s.strip
1406
1814
  end
1407
1815
  end
1408
1816
 
@@ -1427,18 +1835,13 @@ paragraph
1427
1835
 
1428
1836
  section paragraph
1429
1837
  EOS
1430
- output, errors = nil
1431
- redirect_streams do |stdout, stderr|
1432
- output = render_string input
1433
- errors = stderr.string
1434
- end
1838
+ output = render_string input
1435
1839
  assert_xpath '//*[@id="header"]/*', output, 0
1436
1840
  assert_xpath '//*[@id="preamble"]/*', output, 0
1437
1841
  assert_xpath '//*[@id="content"]/h1[text()="Section Title"]', output, 1
1438
1842
  assert_xpath '//*[@class="paragraph"]', output, 1
1439
1843
  assert_xpath '//*[@class="paragraph"]/*[@class="title"][text()="Block title"]', output, 1
1440
- refute_empty errors
1441
- assert_match(/only book doctypes can contain level 0 sections/, errors)
1844
+ assert_message @logger, :ERROR, '<stdin>: line 2: level 0 sections can only be used when doctype is book', Hash
1442
1845
  end
1443
1846
 
1444
1847
  test 'block title above document title gets carried over to first block in first section if no preamble' do
@@ -1467,8 +1870,8 @@ Block content
1467
1870
  EOS
1468
1871
 
1469
1872
  output = render_embedded_string input
1470
- assert output.include?('Block content')
1471
- refute output.include?('[]')
1873
+ assert_includes output, 'Block content'
1874
+ refute_includes output, '[]'
1472
1875
  end
1473
1876
 
1474
1877
  test 'empty block anchor should not appear in output' do
@@ -1480,8 +1883,8 @@ Block content
1480
1883
  EOS
1481
1884
 
1482
1885
  output = render_embedded_string input
1483
- assert output.include?('Block content')
1484
- refute output.include?('[[]]')
1886
+ assert_includes output, 'Block content'
1887
+ refute_includes output, '[[]]'
1485
1888
  end
1486
1889
  end
1487
1890
 
@@ -1570,7 +1973,7 @@ image::http://example.org/tiger-svg[Tiger,100,format=svg]
1570
1973
  image::circle.svg[Tiger,100]
1571
1974
  EOS
1572
1975
 
1573
- output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'docdir' => ::File.dirname(__FILE__) }
1976
+ output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'docdir' => testdir }
1574
1977
  assert_match(/<svg\s[^>]*width="100px"[^>]*>/, output, 1)
1575
1978
  refute_match(/<svg\s[^>]*width="500px"[^>]*>/, output)
1576
1979
  refute_match(/<svg\s[^>]*height="500px"[^>]*>/, output)
@@ -1586,7 +1989,7 @@ image::circle.svg[Tiger,100]
1586
1989
  image::circle.svg[Tiger,100]
1587
1990
  EOS
1588
1991
 
1589
- output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'docdir' => ::File.dirname(__FILE__) }
1992
+ output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'docdir' => testdir }
1590
1993
  assert_match(/<svg\s[^>]*width="100px">/, output, 1)
1591
1994
  end
1592
1995
 
@@ -1596,9 +1999,9 @@ image::circle.svg[Tiger,100]
1596
1999
  image::no-such-image.svg[Alt Text]
1597
2000
  EOS
1598
2001
 
1599
- output, warnings = redirect_streams {|_, err| [(render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER), err.string] }
2002
+ output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER
1600
2003
  assert_xpath '//span[@class="alt"][text()="Alt Text"]', output, 1
1601
- assert_includes warnings, 'SVG does not exist or cannot be read'
2004
+ assert_message @logger, :WARN, '~SVG does not exist or cannot be read'
1602
2005
  end
1603
2006
 
1604
2007
  test 'can render block image with alt text defined in macro containing square bracket' do
@@ -1735,6 +2138,15 @@ image::images/tiger.png[Tiger,link=http://en.wikipedia.org/wiki/Tiger,window=nam
1735
2138
  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
1736
2139
  end
1737
2140
 
2141
+ test 'adds rel=nofollow attribute to block image with a link when the nofollow option is set' do
2142
+ input = <<-EOS
2143
+ image::images/tiger.png[Tiger,link=http://en.wikipedia.org/wiki/Tiger,opts=nofollow]
2144
+ EOS
2145
+
2146
+ output = render_embedded_string input
2147
+ 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
2148
+ end
2149
+
1738
2150
  test 'can render block image with caption' do
1739
2151
  input = <<-EOS
1740
2152
  .The AsciiDoc Tiger
@@ -1743,7 +2155,7 @@ image::images/tiger.png[Tiger]
1743
2155
 
1744
2156
  doc = document_from_string input
1745
2157
  assert_equal 1, doc.blocks[0].number
1746
- output = doc.render
2158
+ output = doc.convert
1747
2159
  assert_xpath '//*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
1748
2160
  assert_xpath '//*[@class="imageblock"]/*[@class="title"][text() = "Figure 1. The AsciiDoc Tiger"]', output, 1
1749
2161
  assert_equal 1, doc.attributes['figure-number']
@@ -1758,7 +2170,7 @@ image::images/tiger.png[Tiger]
1758
2170
 
1759
2171
  doc = document_from_string input
1760
2172
  assert_nil doc.blocks[0].number
1761
- output = doc.render
2173
+ output = doc.convert
1762
2174
  assert_xpath '//*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
1763
2175
  assert_xpath '//*[@class="imageblock"]/*[@class="title"][text() = "Voila! The AsciiDoc Tiger"]', output, 1
1764
2176
  refute doc.attributes.has_key?('figure-number')
@@ -1831,9 +2243,9 @@ image::images/sunset.jpg[Sunset,scaledwidth=25]
1831
2243
  image::{bogus}[]
1832
2244
  EOS
1833
2245
 
1834
- output, warnings = redirect_streams {|_, err| [(render_embedded_string input), err.string] }
1835
- assert output.include?('image::{bogus}[]')
1836
- assert_includes warnings, 'dropping line containing reference to missing attribute'
2246
+ output = render_embedded_string input
2247
+ assert_includes output, 'image::{bogus}[]'
2248
+ assert_message @logger, :WARN, 'dropping line containing reference to missing attribute: bogus'
1837
2249
  end
1838
2250
 
1839
2251
  test 'drops line if image target is missing attribute reference and attribute-missing is drop' do
@@ -1843,9 +2255,9 @@ image::{bogus}[]
1843
2255
  image::{bogus}[]
1844
2256
  EOS
1845
2257
 
1846
- output, warnings = redirect_streams {|_, err| [(render_embedded_string input), err.string] }
2258
+ output = render_embedded_string input
1847
2259
  assert_empty output.strip
1848
- assert_includes warnings, 'dropping line containing reference to missing attribute'
2260
+ assert_message @logger, :WARN, 'dropping line containing reference to missing attribute: bogus'
1849
2261
  end
1850
2262
 
1851
2263
  test 'drops line if image target is missing attribute reference and attribute-missing is drop-line' do
@@ -1855,9 +2267,9 @@ image::{bogus}[]
1855
2267
  image::{bogus}[]
1856
2268
  EOS
1857
2269
 
1858
- output, warnings = redirect_streams {|_, err| [(render_embedded_string input), err.string] }
2270
+ output = render_embedded_string input
1859
2271
  assert_empty output.strip
1860
- assert_includes warnings, 'dropping line containing reference to missing attribute'
2272
+ assert_message @logger, :WARN, 'dropping line containing reference to missing attribute: bogus'
1861
2273
  end
1862
2274
 
1863
2275
  test 'dropped image does not break processing of following section and attribute-missing is drop-line' do
@@ -1869,11 +2281,11 @@ image::{bogus}[]
1869
2281
  == Section Title
1870
2282
  EOS
1871
2283
 
1872
- output, warnings = redirect_streams {|_, err| [(render_embedded_string input), err.string] }
2284
+ output = render_embedded_string input
1873
2285
  assert_css 'img', output, 0
1874
2286
  assert_css 'h2', output, 1
1875
- refute output.include?('== Section Title')
1876
- assert_includes warnings, 'dropping line containing reference to missing attribute'
2287
+ refute_includes output, '== Section Title'
2288
+ assert_message @logger, :WARN, 'dropping line containing reference to missing attribute: bogus'
1877
2289
  end
1878
2290
 
1879
2291
  test 'should pass through image that references uri' do
@@ -1915,9 +2327,9 @@ image::tiger.png[Tiger]
1915
2327
  image::dot.gif[Dot]
1916
2328
  EOS
1917
2329
 
1918
- doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)}
2330
+ doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => testdir }
1919
2331
  assert_equal 'fixtures', doc.attributes['imagesdir']
1920
- output = doc.render
2332
+ output = doc.convert
1921
2333
  assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
1922
2334
  end
1923
2335
 
@@ -1929,11 +2341,11 @@ image::dot.gif[Dot]
1929
2341
  image::unreadable.gif[Dot]
1930
2342
  EOS
1931
2343
 
1932
- doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)}
2344
+ doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => testdir }
1933
2345
  assert_equal 'fixtures', doc.attributes['imagesdir']
1934
- output, warnings = redirect_streams {|_, err| [doc.render, err.string] }
2346
+ output = doc.convert
1935
2347
  assert_xpath '//img[@src="data:image/gif;base64,"]', output, 1
1936
- assert_includes warnings, 'image to embed not found or not readable'
2348
+ assert_message @logger, :WARN, '~image to embed not found or not readable'
1937
2349
  end
1938
2350
 
1939
2351
  test 'embeds base64-encoded data uri for remote image when data-uri attribute is set' do
@@ -1973,16 +2385,12 @@ image::dot.gif[Dot]
1973
2385
  image::#{image_uri}[Missing image]
1974
2386
  EOS
1975
2387
 
1976
- output = warnings = nil
1977
- redirect_streams do |_, err|
1978
- output = using_test_webserver do
1979
- render_embedded_string input, :safe => :safe, :attributes => {'allow-uri-read' => ''}
1980
- end
1981
- warnings = err.string
2388
+ output = using_test_webserver do
2389
+ render_embedded_string input, :safe => :safe, :attributes => {'allow-uri-read' => ''}
1982
2390
  end
1983
2391
 
1984
2392
  assert_xpath %(/*[@class="imageblock"]//img[@src="#{image_uri}"][@alt="Missing image"]), output, 1
1985
- assert_includes warnings, 'could not retrieve image data from URI'
2393
+ assert_message @logger, :WARN, '~could not retrieve image data from URI'
1986
2394
  end
1987
2395
 
1988
2396
  test 'uses remote image uri when data-uri attribute is set and allow-uri-read is not set' do
@@ -2028,13 +2436,13 @@ image::data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=[Do
2028
2436
  image::dot.gif[Dot]
2029
2437
  EOS
2030
2438
 
2031
- doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)}
2439
+ doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => testdir }
2032
2440
  assert_equal '../..//fixtures/./../../fixtures', doc.attributes['imagesdir']
2033
- output, warnings = redirect_streams {|_, err| [doc.render, err.string] }
2441
+ output = doc.convert
2034
2442
  # image target resolves to fixtures/dot.gif relative to docdir (which is explicitly set to the directory of this file)
2035
2443
  # the reference cannot fall outside of the document directory in safe mode
2036
2444
  assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
2037
- assert_includes warnings, 'image has illegal reference to ancestor of jail'
2445
+ assert_message @logger, :WARN, 'image has illegal reference to ancestor of jail; recovering automatically'
2038
2446
  end
2039
2447
 
2040
2448
  test 'cleans reference to ancestor directories in target before reading image if safe mode level is at least SAFE' do
@@ -2045,13 +2453,13 @@ image::dot.gif[Dot]
2045
2453
  image::../..//fixtures/./../../fixtures/dot.gif[Dot]
2046
2454
  EOS
2047
2455
 
2048
- doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)}
2456
+ doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => { 'docdir' => testdir }
2049
2457
  assert_equal './', doc.attributes['imagesdir']
2050
- output, warnings = redirect_streams {|_, err| [doc.render, err.string] }
2458
+ output = doc.convert
2051
2459
  # image target resolves to fixtures/dot.gif relative to docdir (which is explicitly set to the directory of this file)
2052
2460
  # the reference cannot fall outside of the document directory in safe mode
2053
2461
  assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
2054
- assert_includes warnings, 'image has illegal reference to ancestor of jail'
2462
+ assert_message @logger, :WARN, 'image has illegal reference to ancestor of jail; recovering automatically'
2055
2463
  end
2056
2464
  end
2057
2465
 
@@ -2293,7 +2701,22 @@ Override the icon of an admonition block using an attribute
2293
2701
  You can use icons for admonitions by setting the 'icons' attribute.
2294
2702
  EOS
2295
2703
 
2296
- output = render_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)}
2704
+ output = render_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => { 'docdir' => testdir }
2705
+ assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Tip"]', output, 1
2706
+ end
2707
+
2708
+ test 'should embed base64-encoded data uri of custom icon when data-uri attribute is set' do
2709
+ input = <<-EOS
2710
+ :icons:
2711
+ :iconsdir: fixtures
2712
+ :icontype: gif
2713
+ :data-uri:
2714
+
2715
+ [TIP,icon=tip]
2716
+ You can set a custom icon using the icon attribute on the block.
2717
+ EOS
2718
+
2719
+ output = render_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => { 'docdir' => testdir }
2297
2720
  assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Tip"]', output, 1
2298
2721
  end
2299
2722
 
@@ -2323,11 +2746,9 @@ You can use icons for admonitions by setting the 'icons' attribute.
2323
2746
  You can use icons for admonitions by setting the 'icons' attribute.
2324
2747
  EOS
2325
2748
 
2326
- output, warnings = redirect_streams do |_, err|
2327
- [(render_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)}), err.string]
2328
- end
2749
+ output = render_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => { 'docdir' => testdir }
2329
2750
  assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Tip"]', output, 1
2330
- assert_includes warnings, 'image has illegal reference to ancestor of jail'
2751
+ assert_message @logger, :WARN, 'image has illegal reference to ancestor of jail; recovering automatically'
2331
2752
  end
2332
2753
 
2333
2754
  test 'should import Font Awesome and use font-based icons when value of icons attribute is font' do
@@ -2339,7 +2760,7 @@ You can use icons for admonitions by setting the 'icons' attribute.
2339
2760
  EOS
2340
2761
 
2341
2762
  output = render_string input, :safe => Asciidoctor::SafeMode::SERVER
2342
- assert_css 'html > head > link[rel="stylesheet"][href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css"]', output, 1
2763
+ 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
2343
2764
  assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/i[@class="fa icon-tip"]', output, 1
2344
2765
  end
2345
2766
 
@@ -2370,7 +2791,7 @@ puts "AsciiDoc, FTW!"
2370
2791
  EOS
2371
2792
 
2372
2793
  output = render_string input, :safe => Asciidoctor::SafeMode::SAFE
2373
- assert_css 'html > head > link[rel="stylesheet"][href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css"]', output, 1
2794
+ 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
2374
2795
  assert_css 'html > body > script[src="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"]', output, 1
2375
2796
  end
2376
2797
 
@@ -2387,32 +2808,31 @@ puts "AsciiDoc, FTW!"
2387
2808
  EOS
2388
2809
 
2389
2810
  output = render_string input, :safe => Asciidoctor::SafeMode::SAFE
2390
- assert_css 'html > head > link[rel="stylesheet"][href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css"]', output, 1
2811
+ 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
2391
2812
  assert_css 'html > body > script[src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"]', output, 1
2392
2813
  end
2393
2814
  end
2394
2815
 
2395
2816
  context 'Image paths' do
2396
-
2397
2817
  test 'restricts access to ancestor directories when safe mode level is at least SAFE' do
2398
2818
  input = <<-EOS
2399
2819
  image::asciidoctor.png[Asciidoctor]
2400
2820
  EOS
2401
- basedir = File.expand_path File.dirname(__FILE__)
2821
+ basedir = testdir
2402
2822
  block = block_from_string input, :attributes => {'docdir' => basedir}
2403
2823
  doc = block.document
2404
2824
  assert doc.safe >= Asciidoctor::SafeMode::SAFE
2405
2825
 
2406
2826
  assert_equal File.join(basedir, 'images'), block.normalize_asset_path('images')
2407
- assert_equal File.join(basedir, 'etc/images'), redirect_streams { block.normalize_asset_path("#{disk_root}etc/images") }
2408
- assert_equal File.join(basedir, 'images'), redirect_streams { block.normalize_asset_path('../../images') }
2827
+ assert_equal File.join(basedir, 'etc/images'), block.normalize_asset_path("#{disk_root}etc/images")
2828
+ assert_equal File.join(basedir, 'images'), block.normalize_asset_path('../../images')
2409
2829
  end
2410
2830
 
2411
2831
  test 'does not restrict access to ancestor directories when safe mode is disabled' do
2412
2832
  input = <<-EOS
2413
2833
  image::asciidoctor.png[Asciidoctor]
2414
2834
  EOS
2415
- basedir = File.expand_path File.dirname(__FILE__)
2835
+ basedir = testdir
2416
2836
  block = block_from_string input, :safe => Asciidoctor::SafeMode::UNSAFE, :attributes => {'docdir' => basedir}
2417
2837
  doc = block.document
2418
2838
  assert doc.safe == Asciidoctor::SafeMode::UNSAFE
@@ -2686,7 +3106,7 @@ public class Printer {
2686
3106
  assert_match(/\.<em>out<\/em>\./, output, 1)
2687
3107
  assert_match(/\*asterisks\*/, output, 1)
2688
3108
  assert_match(/<strong>bold<\/strong>/, output, 1)
2689
- refute output.include?(Asciidoctor::Substitutors::PASS_START)
3109
+ refute_includes output, Asciidoctor::Substitutors::PASS_START
2690
3110
  end
2691
3111
 
2692
3112
  test 'should link to CodeRay stylesheet if source-highlighter is coderay and linkcss is set' do
@@ -2780,6 +3200,23 @@ puts HTML::Pipeline.new(filters, {}).call(input)[:output]
2780
3200
  doc = document_from_string input, :safe => Asciidoctor::SafeMode::SERVER
2781
3201
  assert_nil doc.attributes['source-highlighter']
2782
3202
  end
3203
+
3204
+ test 'should warn if listing block is not terminated' do
3205
+ input = <<-EOS
3206
+ outside
3207
+
3208
+ ----
3209
+ inside
3210
+
3211
+ still inside
3212
+
3213
+ eof
3214
+ EOS
3215
+
3216
+ output = render_embedded_string input
3217
+ assert_xpath '/*[@class="listingblock"]', output, 1
3218
+ assert_message @logger, :WARN, '<stdin>: line 3: unterminated listing block', Hash
3219
+ end
2783
3220
  end
2784
3221
 
2785
3222
  context 'Abstract and Part Intro' do
@@ -2852,15 +3289,9 @@ Abstract for book with title is valid
2852
3289
  Abstract for book without title is invalid.
2853
3290
  EOS
2854
3291
 
2855
- warnings = nil
2856
- output = nil
2857
- redirect_streams do |stdout, stderr|
2858
- output = render_string input
2859
- warnings = stderr.string
2860
- end
3292
+ output = render_string input
2861
3293
  assert_css '.abstract', output, 0
2862
- refute_nil warnings
2863
- assert_match(/WARNING:.*abstract block/, warnings)
3294
+ assert_message @logger, :WARN, 'abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
2864
3295
  end
2865
3296
 
2866
3297
  test 'should make abstract on open block without title rendered to DocBook' do
@@ -2918,15 +3349,9 @@ Abstract for book with title is valid
2918
3349
  Abstract for book is invalid.
2919
3350
  EOS
2920
3351
 
2921
- output = nil
2922
- warnings = nil
2923
- redirect_streams do |stdout, stderr|
2924
- output = render_string input, :backend => 'docbook'
2925
- warnings = stderr.string
2926
- end
3352
+ output = render_string input, :backend => 'docbook'
2927
3353
  assert_css 'abstract', output, 0
2928
- refute_nil warnings
2929
- assert_match(/WARNING:.*abstract block/, warnings)
3354
+ assert_message @logger, :WARN, 'abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
2930
3355
  end
2931
3356
 
2932
3357
  # TODO partintro shouldn't be recognized if doctype is not book, should be in proper place
@@ -2995,9 +3420,9 @@ content
2995
3420
  part intro paragraph
2996
3421
  EOS
2997
3422
 
2998
- output, warnings = redirect_streams {|_, err| [(render_string input), err.string] }
3423
+ output = render_string input
2999
3424
  assert_css '.partintro', output, 0
3000
- assert_includes warnings, 'partintro block can only be used when doctype is book and it\'s a child of a book part'
3425
+ 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.'
3001
3426
  end
3002
3427
 
3003
3428
  test 'should not allow partintro unless doctype is book' do
@@ -3006,9 +3431,9 @@ part intro paragraph
3006
3431
  part intro paragraph
3007
3432
  EOS
3008
3433
 
3009
- output, warnings = redirect_streams {|_, err| [(render_string input), err.string] }
3434
+ output = render_string input
3010
3435
  assert_css '.partintro', output, 0
3011
- assert_includes warnings, 'partintro block can only be used when doctype is book and it\'s a child of a book part'
3436
+ 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.'
3012
3437
  end
3013
3438
 
3014
3439
  test 'should accept partintro on open block without title rendered to DocBook' do
@@ -3070,9 +3495,9 @@ content
3070
3495
  part intro paragraph
3071
3496
  EOS
3072
3497
 
3073
- output, warnings = redirect_streams {|_, err| [(render_string input, :backend => 'docbook'), err.string] }
3498
+ output = render_string input, :backend => 'docbook'
3074
3499
  assert_css 'partintro', output, 0
3075
- assert_includes warnings, 'partintro block can only be used when doctype is book and it\'s a child of a part section'
3500
+ 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.'
3076
3501
  end
3077
3502
 
3078
3503
  test 'should not allow partintro unless doctype is book rendered to DocBook' do
@@ -3081,9 +3506,9 @@ part intro paragraph
3081
3506
  part intro paragraph
3082
3507
  EOS
3083
3508
 
3084
- output, warnings = redirect_streams {|_, err| [(render_string input, :backend => 'docbook'), err.string] }
3509
+ output = render_string input, :backend => 'docbook'
3085
3510
  assert_css 'partintro', output, 0
3086
- assert_includes warnings, 'partintro block can only be used when doctype is book and it\'s a child of a part section'
3511
+ 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.'
3087
3512
  end
3088
3513
  end
3089
3514
 
@@ -3148,15 +3573,15 @@ content
3148
3573
 
3149
3574
  [subs="attributes+,-verbatim,+specialcharacters,+macros"]
3150
3575
  ....
3151
- http://{application}.org[{gt}{gt}] <1>
3576
+ https://{application}.org[{gt}{gt}] <1>
3152
3577
  ....
3153
3578
  EOS
3154
3579
 
3155
3580
  doc = document_from_string input, :header_footer => false
3156
3581
  block = doc.blocks.first
3157
3582
  assert_equal [:attributes, :specialcharacters, :macros], block.subs
3158
- result = doc.render
3159
- assert result.include?('<pre><a href="http://asciidoctor.org">&gt;&gt;</a> &lt;1&gt;</pre>')
3583
+ result = doc.convert
3584
+ assert_includes result, '<pre><a href="https://asciidoctor.org">&gt;&gt;</a> &lt;1&gt;</pre>'
3160
3585
  end
3161
3586
 
3162
3587
  test 'should be able to set subs then modify them' do
@@ -3168,8 +3593,8 @@ _hey now_ <1>
3168
3593
  doc = document_from_string input, :header_footer => false
3169
3594
  block = doc.blocks.first
3170
3595
  assert_equal [:specialcharacters], block.subs
3171
- result = doc.render
3172
- assert result.include?('_hey now_ &lt;1&gt;')
3596
+ result = doc.convert
3597
+ assert_includes result, '_hey now_ &lt;1&gt;'
3173
3598
  end
3174
3599
  end
3175
3600