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
@@ -17,6 +17,15 @@ context 'Substitutions' do
17
17
  assert_equal %{<em class="blue"><a href="http://asciidoc.org">AsciiDoc</a></em> &amp; <strong class="red">Ruby</strong>\n&#167; Making <u>documentation</u> together<br>\nsince &#169; 2012.}, result
18
18
  end
19
19
 
20
+ test 'apply_subs should not modify string directly' do
21
+ input = '<html> -- the root of all web'
22
+ para = block_from_string input
23
+ para_source = para.source
24
+ result = para.apply_subs para_source
25
+ assert_equal '&lt;html&gt;&#8201;&#8212;&#8201;the root of all web', result
26
+ assert_equal input, para_source
27
+ end
28
+
20
29
  test 'should not drop trailing blank lines when performing substitutions' do
21
30
  para = block_from_string %([%hardbreaks]\nthis\nis\n-> {program})
22
31
  para.lines << ''
@@ -28,15 +37,12 @@ context 'Substitutions' do
28
37
  assert_equal %(this<br>\nis<br>\n&#8594; Asciidoctor<br>\n<br>\n), result
29
38
  end
30
39
 
31
- test 'should expand subs passed to apply_subs when expand argument is set' do
40
+ test 'should expand subs passe to expand_subs' do
32
41
  para = block_from_string %({program}\n*bold*\n2 > 1)
33
42
  para.document.attributes['program'] = 'Asciidoctor'
34
- result = para.apply_subs para.lines, [:specialchars], true
35
- assert_equal ['{program}', '*bold*', '2 &gt; 1'], result
36
- result = para.apply_subs para.lines, [:none], true
37
- assert_equal ['{program}', '*bold*', '2 > 1'], result
38
- result = para.apply_subs para.lines, [:normal], true
39
- assert_equal ['Asciidoctor', '<strong>bold</strong>', '2 &gt; 1'], result
43
+ assert_equal [:specialcharacters], (para.expand_subs [:specialchars])
44
+ refute para.expand_subs([:none])
45
+ assert_equal [:specialcharacters, :quotes, :attributes, :replacements, :macros, :post_replacements], (para.expand_subs [:normal])
40
46
  end
41
47
 
42
48
  test 'apply_subs should allow the subs argument to be nil' do
@@ -53,6 +59,9 @@ context 'Substitutions' do
53
59
 
54
60
  para = block_from_string(%q{"`a few quoted words`"})
55
61
  assert_equal '&#8220;a few quoted words&#8221;', para.sub_quotes(para.source)
62
+
63
+ para = block_from_string(%q{"`a few quoted words`"}, :backend => 'docbook')
64
+ assert_equal '<quote>a few quoted words</quote>', para.sub_quotes(para.source)
56
65
  end
57
66
 
58
67
  test 'escaped single-line double-quoted string' do
@@ -107,6 +116,9 @@ context 'Substitutions' do
107
116
 
108
117
  para = block_from_string(%q{'`a few quoted words`'})
109
118
  assert_equal '&#8216;a few quoted words&#8217;', para.sub_quotes(para.source)
119
+
120
+ para = block_from_string(%q{'`a few quoted words`'}, :backend => 'docbook')
121
+ assert_equal '<quote>a few quoted words</quote>', para.sub_quotes(para.source)
110
122
  end
111
123
 
112
124
  test 'escaped single-line single-quoted string' do
@@ -538,12 +550,12 @@ context 'Substitutions' do
538
550
 
539
551
  test 'quoted text with id shorthand' do
540
552
  para = block_from_string(%q{[#bond]#007#})
541
- assert_equal '<a id="bond"></a>007', para.sub_quotes(para.source)
553
+ assert_equal '<span id="bond">007</span>', para.sub_quotes(para.source)
542
554
  end
543
555
 
544
556
  test 'quoted text with id and role shorthand' do
545
557
  para = block_from_string(%q{[#bond.white.red-background]#007#})
546
- assert_equal '<a id="bond"></a><span class="white red-background">007</span>', para.sub_quotes(para.source)
558
+ assert_equal '<span id="bond" class="white red-background">007</span>', para.sub_quotes(para.source)
547
559
  end
548
560
 
549
561
  test 'quoted text with id and role shorthand using docbook backend' do
@@ -593,12 +605,12 @@ context 'Substitutions' do
593
605
  end
594
606
 
595
607
  test 'a mailto macro with text and subject should be interpreted as a mailto link' do
596
- para = block_from_string('mailto:doc.writer@asciidoc.org[Doc Writer, Pull request]', :attributes => {'linkattrs' => ''})
608
+ para = block_from_string('mailto:doc.writer@asciidoc.org[Doc Writer, Pull request]')
597
609
  assert_equal %q{<a href="mailto:doc.writer@asciidoc.org?subject=Pull%20request">Doc Writer</a>}, para.sub_macros(para.source)
598
610
  end
599
611
 
600
612
  test 'a mailto macro with text, subject and body should be interpreted as a mailto link' do
601
- para = block_from_string('mailto:doc.writer@asciidoc.org[Doc Writer, Pull request, Please accept my pull request]', :attributes => {'linkattrs' => ''})
613
+ para = block_from_string('mailto:doc.writer@asciidoc.org[Doc Writer, Pull request, Please accept my pull request]')
602
614
  assert_equal %q{<a href="mailto:doc.writer@asciidoc.org?subject=Pull%20request&amp;body=Please%20accept%20my%20pull%20request">Doc Writer</a>}, para.sub_macros(para.source)
603
615
  end
604
616
 
@@ -698,7 +710,7 @@ context 'Substitutions' do
698
710
  end
699
711
 
700
712
  test 'an image macro with an inline SVG image should be converted to an svg element' do
701
- para = block_from_string('image:circle.svg[Tiger,100,opts=inline]', :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'imagesdir' => 'fixtures', 'docdir' => ::File.dirname(__FILE__) })
713
+ para = block_from_string('image:circle.svg[Tiger,100,opts=inline]', :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'imagesdir' => 'fixtures', 'docdir' => testdir })
702
714
  result = para.sub_macros(para.source).gsub(/>\s+</, '><')
703
715
  assert_match(/<svg\s[^>]*width="100px"[^>]*>/, result)
704
716
  refute_match(/<svg\s[^>]*width="500px"[^>]*>/, result)
@@ -707,7 +719,7 @@ context 'Substitutions' do
707
719
  end
708
720
 
709
721
  test 'an image macro with an inline SVG image should be converted to an svg element even when data-uri is set' do
710
- para = block_from_string('image:circle.svg[Tiger,100,opts=inline]', :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'data-uri' => '', 'imagesdir' => 'fixtures', 'docdir' => ::File.dirname(__FILE__) })
722
+ para = block_from_string('image:circle.svg[Tiger,100,opts=inline]', :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'data-uri' => '', 'imagesdir' => 'fixtures', 'docdir' => testdir })
711
723
  assert_match(/<svg\s[^>]*width="100px">/, para.sub_macros(para.source).gsub(/>\s+</, '><'))
712
724
  end
713
725
 
@@ -751,6 +763,12 @@ context 'Substitutions' do
751
763
  para.sub_macros(para.source).gsub(/>\s+</, '><')
752
764
  end
753
765
 
766
+ test 'rel=nofollow should be added to an image with a link when the nofollow option is set' do
767
+ para = block_from_string 'image:tiger.png[Tiger,link=http://en.wikipedia.org/wiki/Tiger,opts=nofollow]'
768
+ assert_equal %{<span class="image"><a class="image" href="http://en.wikipedia.org/wiki/Tiger" rel="nofollow"><img src="tiger.png" alt="Tiger"></a></span>},
769
+ para.sub_macros(para.source).gsub(/>\s+</, '><')
770
+ end
771
+
754
772
  test 'a multi-line image macro with text and dimensions should be interpreted as an image with alt text and dimensions' do
755
773
  para = block_from_string(%(image:tiger.png[Another\nAwesome\nTiger, 200,\n100]))
756
774
  assert_equal %{<span class="image"><img src="tiger.png" alt="Another Awesome Tiger" width="200" height="100"></span>},
@@ -796,7 +814,7 @@ context 'Substitutions' do
796
814
  test 'should not match an inline image macro if target contains an endline character' do
797
815
  para = block_from_string(%(Fear not. There are no image:big\ncats.png[] around here.))
798
816
  result = para.sub_macros(para.source)
799
- refute result.include?('<img ')
817
+ refute_includes result, '<img '
800
818
  assert_includes result, %(image:big\ncats.png[])
801
819
  end
802
820
 
@@ -804,7 +822,7 @@ context 'Substitutions' do
804
822
  ['image: big cats.png[]', 'image:big cats.png []'].each do |input|
805
823
  para = block_from_string %(Fear not. There are no #{input} around here.)
806
824
  result = para.sub_macros(para.source)
807
- refute result.include?('<img ')
825
+ refute_includes result, '<img '
808
826
  assert_includes result, input
809
827
  end
810
828
  end
@@ -812,8 +830,8 @@ context 'Substitutions' do
812
830
  test 'should not detect a block image macro found inline' do
813
831
  para = block_from_string(%(Not an inline image macro image::tiger.png[].))
814
832
  result = para.sub_macros(para.source)
815
- refute result.include?('<img ')
816
- assert result.include?('image::tiger.png[]')
833
+ refute_includes result, '<img '
834
+ assert_includes result, 'image::tiger.png[]'
817
835
  end
818
836
 
819
837
  # NOTE this test verifies attributes get substituted eagerly in target of image in title
@@ -822,12 +840,11 @@ context 'Substitutions' do
822
840
  == image:{iconsdir}/dot.gif[dot] Title
823
841
  EOS
824
842
 
825
- sect, warnings = redirect_streams do |_, err|
826
- [(block_from_string input, :attributes => { 'data-uri' => '', 'iconsdir' => 'fixtures', 'docdir' => ::File.dirname(__FILE__) }, :safe => :server, :catalog_assets => true), err.string]
843
+ using_memory_logger do |logger|
844
+ sect = block_from_string input, :attributes => { 'data-uri' => '', 'iconsdir' => 'fixtures', 'docdir' => testdir }, :safe => :server, :catalog_assets => true
845
+ assert_includes sect.document.catalog[:images], 'fixtures/dot.gif'
846
+ assert logger.empty?
827
847
  end
828
- assert sect.document.catalog[:images].include? 'fixtures/dot.gif'
829
- refute_nil warnings
830
- assert_empty warnings
831
848
  end
832
849
 
833
850
  test 'an icon macro should be interpreted as an icon if icons are enabled' do
@@ -862,7 +879,7 @@ context 'Substitutions' do
862
879
 
863
880
  test 'a single-line footnote macro should be registered and rendered as a footnote' do
864
881
  para = block_from_string('Sentence text footnote:[An example footnote.].')
865
- assert_equal %(Sentence text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
882
+ assert_equal %(Sentence text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
866
883
  assert_equal 1, para.document.catalog[:footnotes].size
867
884
  footnote = para.document.catalog[:footnotes].first
868
885
  assert_equal 1, footnote.index
@@ -872,7 +889,7 @@ context 'Substitutions' do
872
889
 
873
890
  test 'a multi-line footnote macro should be registered and rendered as a footnote without endline' do
874
891
  para = block_from_string("Sentence text footnote:[An example footnote\nwith wrapped text.].")
875
- assert_equal %(Sentence text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
892
+ assert_equal %(Sentence text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
876
893
  assert_equal 1, para.document.catalog[:footnotes].size
877
894
  footnote = para.document.catalog[:footnotes].first
878
895
  assert_equal 1, footnote.index
@@ -882,7 +899,7 @@ context 'Substitutions' do
882
899
 
883
900
  test 'an escaped closing square bracket in a footnote should be unescaped when rendered' do
884
901
  para = block_from_string(%(footnote:[a #{BACKSLASH}] b].))
885
- assert_equal %(<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
902
+ assert_equal %(<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
886
903
  assert_equal 1, para.document.catalog[:footnotes].size
887
904
  footnote = para.document.catalog[:footnotes].first
888
905
  assert_equal "a ] b", footnote.text
@@ -890,7 +907,7 @@ context 'Substitutions' do
890
907
 
891
908
  test 'a footnote macro can be directly adjacent to preceding word' do
892
909
  para = block_from_string('Sentence textfootnote:[An example footnote.].')
893
- assert_equal %(Sentence text<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
910
+ assert_equal %(Sentence text<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
894
911
  end
895
912
 
896
913
  test 'a footnote macro may contain an escaped backslash' do
@@ -907,7 +924,7 @@ context 'Substitutions' do
907
924
 
908
925
  test 'a footnote macro may contain a link macro' do
909
926
  para = block_from_string('Share your code. footnote:[https://github.com[GitHub]]')
910
- assert_equal %(Share your code. <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup>), para.sub_macros(para.source)
927
+ assert_equal %(Share your code. <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>), para.sub_macros(para.source)
911
928
  assert_equal 1, para.document.catalog[:footnotes].size
912
929
  footnote1 = para.document.catalog[:footnotes][0]
913
930
  assert_equal '<a href="https://github.com">GitHub</a>', footnote1.text
@@ -916,7 +933,7 @@ context 'Substitutions' do
916
933
  test 'a footnote macro may contain a plain URL' do
917
934
  para = block_from_string %(the JLine footnote:[https://github.com/jline/jline2]\nlibrary.)
918
935
  result = para.sub_macros para.source
919
- assert_equal %(the JLine <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup>\nlibrary.), result
936
+ assert_equal %(the JLine <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>\nlibrary.), result
920
937
  assert_equal 1, para.document.catalog[:footnotes].size
921
938
  fn1 = para.document.catalog[:footnotes].first
922
939
  assert_equal '<a href="https://github.com/jline/jline2" class="bare">https://github.com/jline/jline2</a>', fn1.text
@@ -925,7 +942,7 @@ context 'Substitutions' do
925
942
  test 'a footnote macro followed by a semi-colon may contain a plain URL' do
926
943
  para = block_from_string %(the JLine footnote:[https://github.com/jline/jline2];\nlibrary.)
927
944
  result = para.sub_macros para.source
928
- assert_equal %(the JLine <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup>;\nlibrary.), result
945
+ assert_equal %(the JLine <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>;\nlibrary.), result
929
946
  assert_equal 1, para.document.catalog[:footnotes].size
930
947
  fn1 = para.document.catalog[:footnotes].first
931
948
  assert_equal '<a href="https://github.com/jline/jline2" class="bare">https://github.com/jline/jline2</a>', fn1.text
@@ -937,7 +954,7 @@ context 'Substitutions' do
937
954
  doc = para.document
938
955
  doc.register :refs, ['_install', (Asciidoctor::Inline.new doc, :anchor, 'Install', :type => :ref, :target => '_install'), 'Install']
939
956
  catalog = doc.catalog
940
- assert_equal %(text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup>), para.sub_macros(para.source)
957
+ assert_equal %(text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>), para.sub_macros(para.source)
941
958
  assert_equal 1, catalog[:footnotes].size
942
959
  footnote1 = catalog[:footnotes][0]
943
960
  assert_equal '<a href="#_install">install</a>', footnote1.text
@@ -945,7 +962,7 @@ context 'Substitutions' do
945
962
 
946
963
  test 'a footnote macro may contain an anchor macro' do
947
964
  para = block_from_string('text footnote:[a [[b\]\] \[[c\]\] d]')
948
- assert_equal %(text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup>), para.sub_macros(para.source)
965
+ assert_equal %(text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>), para.sub_macros(para.source)
949
966
  assert_equal 1, para.document.catalog[:footnotes].size
950
967
  footnote1 = para.document.catalog[:footnotes][0]
951
968
  assert_equal 'a <a id="b"></a> [[c]] d', footnote1.text
@@ -962,7 +979,7 @@ foofootnote:[+http://example.com+]barfootnote:[+http://acme.com+]baz
962
979
 
963
980
  test 'should increment index of subsequent footnote macros' do
964
981
  para = block_from_string("Sentence text footnote:[An example footnote.]. Sentence text footnote:[Another footnote.].")
965
- assert_equal %(Sentence text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup>. Sentence text <sup class="footnote">[<a id="_footnoteref_2" class="footnote" href="#_footnote_2" title="View footnote.">2</a>]</sup>.), para.sub_macros(para.source)
982
+ assert_equal %(Sentence text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>. Sentence text <sup class="footnote">[<a id="_footnoteref_2" class="footnote" href="#_footnotedef_2" title="View footnote.">2</a>]</sup>.), para.sub_macros(para.source)
966
983
  assert_equal 2, para.document.catalog[:footnotes].size
967
984
  footnote1 = para.document.catalog[:footnotes][0]
968
985
  assert_equal 1, footnote1.index
@@ -976,7 +993,7 @@ foofootnote:[+http://example.com+]barfootnote:[+http://acme.com+]baz
976
993
 
977
994
  test 'a footnoteref macro with id and single-line text should be registered and rendered as a footnote' do
978
995
  para = block_from_string('Sentence text footnoteref:[ex1, An example footnote.].')
979
- assert_equal %(Sentence text <sup class="footnote" id="_footnote_ex1">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
996
+ assert_equal %(Sentence text <sup class="footnote" id="_footnote_ex1">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
980
997
  assert_equal 1, para.document.catalog[:footnotes].size
981
998
  footnote = para.document.catalog[:footnotes].first
982
999
  assert_equal 1, footnote.index
@@ -986,7 +1003,7 @@ foofootnote:[+http://example.com+]barfootnote:[+http://acme.com+]baz
986
1003
 
987
1004
  test 'a footnoteref macro with id and multi-line text should be registered and rendered as a footnote without endlines' do
988
1005
  para = block_from_string("Sentence text footnoteref:[ex1, An example footnote\nwith wrapped text.].")
989
- assert_equal %(Sentence text <sup class="footnote" id="_footnote_ex1">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
1006
+ assert_equal %(Sentence text <sup class="footnote" id="_footnote_ex1">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
990
1007
  assert_equal 1, para.document.catalog[:footnotes].size
991
1008
  footnote = para.document.catalog[:footnotes].first
992
1009
  assert_equal 1, footnote.index
@@ -996,7 +1013,7 @@ foofootnote:[+http://example.com+]barfootnote:[+http://acme.com+]baz
996
1013
 
997
1014
  test 'a footnoteref macro with id should refer to footnoteref with same id' do
998
1015
  para = block_from_string('Sentence text footnoteref:[ex1, An example footnote.]. Sentence text footnoteref:[ex1].')
999
- assert_equal %(Sentence text <sup class="footnote" id="_footnote_ex1">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup>. Sentence text <sup class="footnoteref">[<a class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
1016
+ assert_equal %(Sentence text <sup class="footnote" id="_footnote_ex1">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>. Sentence text <sup class="footnoteref">[<a class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
1000
1017
  assert_equal 1, para.document.catalog[:footnotes].size
1001
1018
  footnote = para.document.catalog[:footnotes].first
1002
1019
  assert_equal 1, footnote.index
@@ -1004,9 +1021,66 @@ foofootnote:[+http://example.com+]barfootnote:[+http://acme.com+]baz
1004
1021
  assert_equal 'An example footnote.', footnote.text
1005
1022
  end
1006
1023
 
1007
- test 'an unresolved footnoteref should not crash the processor' do
1008
- para = block_from_string('Sentence text footnoteref:[ex1].')
1009
- para.sub_macros para.source
1024
+ test 'an unresolved footnote reference should produce a warning message' do
1025
+ input = 'Sentence text.footnote:ex1[]'
1026
+ using_memory_logger do |logger|
1027
+ para = block_from_string input
1028
+ para.sub_macros para.source
1029
+ assert_message logger, :WARN, 'invalid footnote reference: ex1'
1030
+ end
1031
+ end
1032
+
1033
+ test 'inline footnote macro can be used to define and reference a footnote reference' do
1034
+ input = <<-EOS
1035
+ You can download the software from the product page.footnote:sub[Option only available if you have an active subscription.]
1036
+
1037
+ You can also file a support request.footnote:sub[]
1038
+
1039
+ If all else fails, you can give us a call.footnoteref:[sub]
1040
+ EOS
1041
+
1042
+ output = render_embedded_string input
1043
+ assert_css '#_footnotedef_1', output, 1
1044
+ assert_css 'p a[href="#_footnotedef_1"]', output, 3
1045
+ assert_css '#footnotes .footnote', output, 1
1046
+ end
1047
+
1048
+ test 'should parse multiple footnote references in a single line' do
1049
+ input = <<-'EOS'
1050
+ notable text.footnote:id[about this [text\]], footnote:id[], footnote:id[]
1051
+ EOS
1052
+
1053
+ output = render_embedded_string input
1054
+ assert_xpath '(//p)[1]/sup[starts-with(@class,"footnote")]', output, 3
1055
+ assert_xpath '(//p)[1]/sup[@class="footnote"]', output, 1
1056
+ assert_xpath '(//p)[1]/sup[@class="footnoteref"]', output, 2
1057
+ assert_xpath '(//p)[1]/sup[starts-with(@class,"footnote")]/a[@class="footnote"][text()="1"]', output, 3
1058
+ assert_css '#footnotes .footnote', output, 1
1059
+ end
1060
+
1061
+ test 'should not resolve an inline footnote macro missing both id and text' do
1062
+ input = <<-EOS
1063
+ The footnote:[] macro can be used for defining and referencing footnotes.
1064
+
1065
+ The footnoteref:[] macro is now deprecated.
1066
+ EOS
1067
+
1068
+ output = render_embedded_string input
1069
+ assert_includes output, 'The footnote:[] macro'
1070
+ assert_includes output, 'The footnoteref:[] macro'
1071
+ end
1072
+
1073
+ test 'inline footnote macro can define a numeric id without conflicting with auto-generated ID' do
1074
+ input = <<-EOS
1075
+ You can download the software from the product page.footnote:1[Option only available if you have an active subscription.]
1076
+ EOS
1077
+
1078
+ output = render_embedded_string input
1079
+ assert_css '#_footnote_1', output, 1
1080
+ assert_css 'p sup#_footnote_1', output, 1
1081
+ assert_css 'p a#_footnoteref_1', output, 1
1082
+ assert_css 'p a[href="#_footnotedef_1"]', output, 1
1083
+ assert_css '#footnotes #_footnotedef_1', output, 1
1010
1084
  end
1011
1085
 
1012
1086
  test 'a single-line index term macro with a primary term should be registered as an index reference' do
@@ -1057,6 +1131,16 @@ foofootnote:[+http://example.com+]barfootnote:[+http://acme.com+]baz
1057
1131
  end
1058
1132
  end
1059
1133
 
1134
+ test 'should only escape enclosing brackets if concealed index term is preceded by a backslash' do
1135
+ input = %[National Institute of Science and Technology #{BACKSLASH}(((NIST)))]
1136
+ doc = document_from_string input, :header_footer => false
1137
+ output = doc.convert
1138
+ assert_xpath '//p[text()="National Institute of Science and Technology (NIST)"]', output, 1
1139
+ term = doc.catalog[:indexterms].first
1140
+ assert_equal 1, term.size
1141
+ assert_equal 'NIST', term.first
1142
+ end
1143
+
1060
1144
  test 'should not split index terms on commas inside of quoted terms' do
1061
1145
  inputs = []
1062
1146
  inputs.push <<-EOS
@@ -1585,18 +1669,34 @@ EOS
1585
1669
  assert_equal '\$a &lt; b\$', para.content
1586
1670
  end
1587
1671
 
1588
- # NOTE this test doesn't work once AsciiMath has been loaded
1589
- #test 'should not perform specialcharacters subs on asciimath macro content in docbook backend by default' do
1590
- # input = 'asciimath:[a < b]'
1591
- # para = block_from_string input, :backend => :docbook
1592
- # para.document.converter.instance_variable_set :@asciimath_available, false
1593
- # assert_equal '<inlineequation><mathphrase><![CDATA[a < b]]></mathphrase></inlineequation>', para.content
1594
- #end
1672
+ test 'should convert contents of asciimath macro to MathML in DocBook output if asciimath gem is available' do
1673
+ asciimath_available = !(Asciidoctor::Helpers.require_library 'asciimath', true, :ignore).nil?
1674
+ input = 'asciimath:[a < b]'
1675
+ expected = '<inlineequation><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mi>a</mml:mi><mml:mo>&#x003C;</mml:mo><mml:mi>b</mml:mi></mml:math></inlineequation>'
1676
+ using_memory_logger do |logger|
1677
+ para = block_from_string input, :backend => :docbook
1678
+ actual = para.content
1679
+ if asciimath_available
1680
+ assert_equal expected, actual
1681
+ assert_equal :loaded, para.document.converter.instance_variable_get(:@asciimath)
1682
+ else
1683
+ assert_message logger, :WARN, 'optional gem \'asciimath\' is not installed. Functionality disabled.'
1684
+ assert_equal :unavailable, para.document.converter.instance_variable_get(:@asciimath)
1685
+ end
1686
+ end
1687
+ end
1595
1688
 
1596
- test 'should convert asciimath macro content to MathML when asciimath gem is available' do
1689
+ test 'should not perform specialcharacters subs on asciimath macro content in Docbook output if asciimath gem not available' do
1690
+ asciimath_available = !(Asciidoctor::Helpers.require_library 'asciimath', true, :ignore).nil?
1597
1691
  input = 'asciimath:[a < b]'
1598
1692
  para = block_from_string input, :backend => :docbook
1599
- assert_equal '<inlineequation><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mi>a</mml:mi><mml:mo>&#x003C;</mml:mo><mml:mi>b</mml:mi></mml:math></inlineequation>', para.content
1693
+ para.document.converter.instance_variable_set :@asciimath, :unavailable
1694
+ if asciimath_available
1695
+ old_asciimath = ::AsciiMath
1696
+ Object.send :remove_const, 'AsciiMath'
1697
+ end
1698
+ assert_equal '<inlineequation><mathphrase><![CDATA[a < b]]></mathphrase></inlineequation>', para.content
1699
+ ::AsciiMath = old_asciimath if asciimath_available
1600
1700
  end
1601
1701
 
1602
1702
  test 'should honor explicit subslist on asciimath macro' do
@@ -1649,17 +1749,36 @@ EOS
1649
1749
  assert_equal 'the text <code>asciimath:[x = y]</code> should be passed through as <code>literal</code> text', para.content
1650
1750
  end
1651
1751
 
1752
+ test 'should not process an escaped passthrough macro inside a monospaced phrase' do
1753
+ input = 'use the `\pass:c[]` macro'
1754
+ para = block_from_string input
1755
+ assert_equal 'use the <code>pass:c[]</code> macro', para.content
1756
+ end
1757
+
1758
+ test 'should not process an escaped passthrough macro inside a monospaced phrase with attributes' do
1759
+ input = 'use the [syntax]`\pass:c[]` macro'
1760
+ para = block_from_string input
1761
+ assert_equal 'use the <code class="syntax">pass:c[]</code> macro', para.content
1762
+ end
1763
+
1764
+ test 'should honor an escaped single plus passthrough inside a monospaced phrase' do
1765
+ input = 'use `\+{author}+` to show an attribute reference'
1766
+ para = block_from_string input
1767
+ assert_equal 'use <code>+{author}+</code> to show an attribute reference', para.content
1768
+ end
1769
+
1652
1770
  test 'should not recognize stem macro with no content' do
1653
1771
  input = 'stem:[]'
1654
1772
  para = block_from_string input
1655
1773
  assert_equal input, para.content
1656
1774
  end
1657
1775
 
1658
- test 'should passthrough text in stem macro and surround with AsciiMath delimiters if stem attribute != latexmath' do
1776
+ test 'should passthrough text in stem macro and surround with AsciiMath delimiters if stem attribute is asciimath, empty, or not set' do
1659
1777
  [
1660
1778
  {},
1661
1779
  {'stem' => ''},
1662
- {'stem' => 'asciimath'}
1780
+ {'stem' => 'asciimath'},
1781
+ {'stem' => 'bogus'}
1663
1782
  ].each do |attributes|
1664
1783
  input = 'stem:[x/x={(1,if x!=0),(text{undefined},if x=0):}]'
1665
1784
  para = block_from_string input, :attributes => attributes
@@ -1667,10 +1786,16 @@ EOS
1667
1786
  end
1668
1787
  end
1669
1788
 
1670
- test 'should passthrough text in stem macro and surround with LaTeX math delimiters if stem attribute = latexmath' do
1671
- input = 'stem:[C = \alpha + \beta Y^{\gamma} + \epsilon]'
1672
- para = block_from_string input, :attributes => {'stem' => 'latexmath'}
1673
- assert_equal '\(C = \alpha + \beta Y^{\gamma} + \epsilon\)', para.content
1789
+ test 'should passthrough text in stem macro and surround with LaTeX math delimiters if stem attribute is latexmath, latex, or tex' do
1790
+ [
1791
+ {'stem' => 'latexmath'},
1792
+ {'stem' => 'latex'},
1793
+ {'stem' => 'tex'}
1794
+ ].each do |attributes|
1795
+ input = 'stem:[C = \alpha + \beta Y^{\gamma} + \epsilon]'
1796
+ para = block_from_string input, :attributes => attributes
1797
+ assert_equal '\(C = \alpha + \beta Y^{\gamma} + \epsilon\)', para.content
1798
+ end
1674
1799
  end
1675
1800
 
1676
1801
  test 'should apply substitutions specified on stem macro' do
@@ -1779,25 +1904,25 @@ foo&#8201;&#8212;&#8201;'
1779
1904
  context 'Post replacements' do
1780
1905
  test 'line break inserted after line with line break character' do
1781
1906
  para = block_from_string("First line +\nSecond line")
1782
- result = para.apply_subs(para.lines, :post_replacements, true)
1907
+ result = para.apply_subs para.lines, (para.expand_subs :post_replacements)
1783
1908
  assert_equal 'First line<br>', result.first
1784
1909
  end
1785
1910
 
1786
1911
  test 'line break inserted after line wrap with hardbreaks enabled' do
1787
1912
  para = block_from_string("First line\nSecond line", :attributes => {'hardbreaks' => ''})
1788
- result = para.apply_subs(para.lines, :post_replacements, true)
1913
+ result = para.apply_subs para.lines, (para.expand_subs :post_replacements)
1789
1914
  assert_equal 'First line<br>', result.first
1790
1915
  end
1791
1916
 
1792
1917
  test 'line break character stripped from end of line with hardbreaks enabled' do
1793
1918
  para = block_from_string("First line +\nSecond line", :attributes => {'hardbreaks' => ''})
1794
- result = para.apply_subs(para.lines, :post_replacements, true)
1919
+ result = para.apply_subs para.lines, (para.expand_subs :post_replacements)
1795
1920
  assert_equal 'First line<br>', result.first
1796
1921
  end
1797
1922
 
1798
1923
  test 'line break not inserted for single line with hardbreaks enabled' do
1799
1924
  para = block_from_string('First line', :attributes => {'hardbreaks' => ''})
1800
- result = para.apply_subs(para.lines, :post_replacements, true)
1925
+ result = para.apply_subs para.lines, (para.expand_subs :post_replacements)
1801
1926
  assert_equal 'First line', result.first
1802
1927
  end
1803
1928
  end