asciidoctor 1.5.5 → 1.5.6

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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +216 -1
  3. data/CONTRIBUTING.adoc +2 -2
  4. data/Gemfile +20 -1
  5. data/LICENSE.adoc +1 -1
  6. data/README-fr.adoc +4 -3
  7. data/README-jp.adoc +11 -10
  8. data/README-zh_CN.adoc +4 -3
  9. data/README.adoc +17 -202
  10. data/Rakefile +41 -25
  11. data/asciidoctor.gemspec +9 -10
  12. data/data/locale/attributes.adoc +216 -34
  13. data/data/stylesheets/asciidoctor-default.css +23 -16
  14. data/features/step_definitions.rb +15 -19
  15. data/features/xref.feature +584 -20
  16. data/lib/asciidoctor.rb +292 -278
  17. data/lib/asciidoctor/abstract_block.rb +155 -94
  18. data/lib/asciidoctor/abstract_node.rb +108 -94
  19. data/lib/asciidoctor/attribute_list.rb +30 -22
  20. data/lib/asciidoctor/block.rb +7 -7
  21. data/lib/asciidoctor/cli/invoker.rb +47 -34
  22. data/lib/asciidoctor/cli/options.rb +22 -11
  23. data/lib/asciidoctor/converter.rb +3 -3
  24. data/lib/asciidoctor/converter/base.rb +2 -2
  25. data/lib/asciidoctor/converter/composite.rb +1 -1
  26. data/lib/asciidoctor/converter/docbook45.rb +2 -2
  27. data/lib/asciidoctor/converter/docbook5.rb +132 -87
  28. data/lib/asciidoctor/converter/factory.rb +0 -1
  29. data/lib/asciidoctor/converter/html5.rb +116 -98
  30. data/lib/asciidoctor/converter/manpage.rb +51 -52
  31. data/lib/asciidoctor/converter/template.rb +47 -36
  32. data/lib/asciidoctor/core_ext.rb +8 -2
  33. data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +4 -0
  34. data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +6 -0
  35. data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +5 -0
  36. data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +1 -1
  37. data/lib/asciidoctor/core_ext/1.8.7/string/{limit.rb → limit_bytesize.rb} +7 -6
  38. data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +6 -0
  39. data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +1 -1
  40. data/lib/asciidoctor/core_ext/nil_or_empty.rb +5 -5
  41. data/lib/asciidoctor/core_ext/regexp/is_match.rb +3 -0
  42. data/lib/asciidoctor/core_ext/string/{limit.rb → limit_bytesize.rb} +2 -2
  43. data/lib/asciidoctor/document.rb +216 -213
  44. data/lib/asciidoctor/extensions.rb +318 -185
  45. data/lib/asciidoctor/helpers.rb +35 -35
  46. data/lib/asciidoctor/inline.rb +32 -1
  47. data/lib/asciidoctor/list.rb +22 -6
  48. data/lib/asciidoctor/parser.rb +1008 -1038
  49. data/lib/asciidoctor/path_resolver.rb +46 -50
  50. data/lib/asciidoctor/reader.rb +275 -251
  51. data/lib/asciidoctor/section.rb +86 -58
  52. data/lib/asciidoctor/stylesheets.rb +6 -6
  53. data/lib/asciidoctor/substitutors.rb +567 -649
  54. data/lib/asciidoctor/table.rb +163 -108
  55. data/lib/asciidoctor/version.rb +1 -1
  56. data/man/asciidoctor.1 +18 -16
  57. data/man/asciidoctor.adoc +15 -13
  58. data/test/attributes_test.rb +138 -22
  59. data/test/blocks_test.rb +377 -97
  60. data/test/converter_test.rb +13 -0
  61. data/test/document_test.rb +244 -34
  62. data/test/extensions_test.rb +409 -42
  63. data/test/fixtures/asciidoc_index.txt +521 -0
  64. data/test/fixtures/basic-docinfo-footer.html +6 -0
  65. data/test/fixtures/basic-docinfo-footer.xml +8 -0
  66. data/test/fixtures/basic-docinfo.html +1 -0
  67. data/test/fixtures/basic-docinfo.xml +4 -0
  68. data/test/fixtures/basic.asciidoc +5 -0
  69. data/test/fixtures/chapter-a.adoc +3 -0
  70. data/test/fixtures/child-include.adoc +5 -0
  71. data/test/fixtures/circle.svg +9 -0
  72. data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +6 -0
  73. data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +6 -0
  74. data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +1 -0
  75. data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +3 -0
  76. data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +5 -0
  77. data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +6 -0
  78. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +3 -0
  79. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +5 -0
  80. data/test/fixtures/custom-docinfodir/basic-docinfo.html +1 -0
  81. data/test/fixtures/custom-docinfodir/docinfo.html +1 -0
  82. data/test/fixtures/docinfo-footer.html +1 -0
  83. data/test/fixtures/docinfo-footer.xml +9 -0
  84. data/test/fixtures/docinfo.html +1 -0
  85. data/test/fixtures/docinfo.xml +3 -0
  86. data/test/fixtures/dot.gif +0 -0
  87. data/test/fixtures/encoding.asciidoc +13 -0
  88. data/test/fixtures/grandchild-include.adoc +3 -0
  89. data/test/fixtures/hello-asciidoctor.pdf +69 -0
  90. data/test/fixtures/include-file.asciidoc +24 -0
  91. data/test/fixtures/include-file.ml +3 -0
  92. data/test/fixtures/include-file.xml +5 -0
  93. data/test/fixtures/master.adoc +5 -0
  94. data/test/fixtures/mismatched-end-tag.adoc +7 -0
  95. data/test/fixtures/parent-include-restricted.adoc +5 -0
  96. data/test/fixtures/parent-include.adoc +5 -0
  97. data/test/fixtures/sample.asciidoc +26 -0
  98. data/test/fixtures/stylesheets/custom.css +3 -0
  99. data/test/fixtures/subs-docinfo.html +2 -0
  100. data/test/fixtures/subs.adoc +7 -0
  101. data/test/fixtures/tagged-class-enclosed.rb +26 -0
  102. data/test/fixtures/tagged-class.rb +23 -0
  103. data/test/fixtures/tip.gif +0 -0
  104. data/test/invoker_test.rb +82 -4
  105. data/test/links_test.rb +312 -37
  106. data/test/lists_test.rb +204 -25
  107. data/test/manpage_test.rb +191 -4
  108. data/test/options_test.rb +18 -1
  109. data/test/paragraphs_test.rb +32 -7
  110. data/test/parser_test.rb +150 -30
  111. data/test/paths_test.rb +47 -13
  112. data/test/preamble_test.rb +1 -1
  113. data/test/reader_test.rb +366 -126
  114. data/test/sections_test.rb +203 -56
  115. data/test/substitutions_test.rb +339 -131
  116. data/test/tables_test.rb +315 -15
  117. data/test/test_helper.rb +400 -0
  118. data/test/text_test.rb +5 -5
  119. metadata +110 -22
@@ -26,6 +26,19 @@ context 'Converter' do
26
26
  assert_equal :xhtml, selected.templates['paragraph'].options[:format]
27
27
  end
28
28
 
29
+ test 'should configure Slim to resolve includes in specified template dirs' do
30
+ template_dirs = [
31
+ File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'slim'),
32
+ File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'slim-overrides'),
33
+ ]
34
+ doc = Asciidoctor::Document.new [], :template_dirs => template_dirs, :template_cache => false
35
+ assert doc.converter.is_a?(Asciidoctor::Converter::CompositeConverter)
36
+ selected = doc.converter.find_converter('paragraph')
37
+ assert selected.is_a? Asciidoctor::Converter::TemplateConverter
38
+ assert selected.templates['paragraph'].is_a? Slim::Template
39
+ assert_equal template_dirs.reverse.map {|dir| File.expand_path dir }, selected.templates['paragraph'].options[:include_dirs]
40
+ end
41
+
29
42
  test 'should set Slim format to html for html5 backend' do
30
43
  doc = Asciidoctor::Document.new [], :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'slim'), :template_cache => false
31
44
  assert doc.converter.is_a?(Asciidoctor::Converter::CompositeConverter)
@@ -13,6 +13,9 @@ context 'Document' do
13
13
  doc = example_document(:asciidoc_index)
14
14
  assert_equal 'AsciiDoc Home Page', doc.doctitle
15
15
  assert_equal 'AsciiDoc Home Page', doc.name
16
+ refute_nil doc.header
17
+ assert_equal :section, doc.header.context
18
+ assert_equal 'header', doc.header.sectname
16
19
  assert_equal 14, doc.blocks.size
17
20
  assert_equal :preamble, doc.blocks[0].context
18
21
  assert doc.blocks[1].context == :section
@@ -106,6 +109,18 @@ context 'Document' do
106
109
  assert !doc.attr?('sectnums')
107
110
  end
108
111
 
112
+ test 'noheader attribute should suppress info element when converting to DocBook' do
113
+ input = <<-EOS
114
+ = Document Title
115
+ :noheader:
116
+
117
+ content
118
+ EOS
119
+ result = render_string input, :backend => 'docbook'
120
+ assert_xpath '/article', result, 1
121
+ assert_xpath '/article/info', result, 0
122
+ end
123
+
109
124
  test 'should be able to disable section numbering using numbered attribute in document header for DocBook backend' do
110
125
  input = <<-EOS
111
126
  = Document Title
@@ -119,10 +134,11 @@ context 'Document' do
119
134
  context 'Load APIs' do
120
135
  test 'should load input file' do
121
136
  sample_input_path = fixture_path('sample.asciidoc')
122
- doc = Asciidoctor.load(File.new(sample_input_path), :safe => Asciidoctor::SafeMode::SAFE)
137
+ doc = File.open(sample_input_path) {|file| Asciidoctor.load file, :safe => Asciidoctor::SafeMode::SAFE }
123
138
  assert_equal 'Document Title', doc.doctitle
124
139
  assert_equal File.expand_path(sample_input_path), doc.attr('docfile')
125
140
  assert_equal File.expand_path(File.dirname(sample_input_path)), doc.attr('docdir')
141
+ assert_equal '.asciidoc', doc.attr('docfilesuffix')
126
142
  end
127
143
 
128
144
  test 'should load input file from filename' do
@@ -131,6 +147,7 @@ context 'Document' do
131
147
  assert_equal 'Document Title', doc.doctitle
132
148
  assert_equal File.expand_path(sample_input_path), doc.attr('docfile')
133
149
  assert_equal File.expand_path(File.dirname(sample_input_path)), doc.attr('docdir')
150
+ assert_equal '.asciidoc', doc.attr('docfilesuffix')
134
151
  end
135
152
 
136
153
  test 'should not load invalid file' do
@@ -204,8 +221,10 @@ preamble
204
221
  end
205
222
 
206
223
  test 'should accept attributes as string' do
207
- # NOTE there's a tab character before idseparator
208
- doc = Asciidoctor.load('text', :attributes => 'toc sectnums source-highlighter=coderay idprefix idseparator=-')
224
+ doc = Asciidoctor.load('text', :attributes => 'toc sectnums
225
+ source-highlighter=coderay
226
+ idprefix
227
+ idseparator=-')
209
228
  assert doc.attributes.is_a?(Hash)
210
229
  assert doc.attr?('toc')
211
230
  assert_equal '', doc.attr('toc')
@@ -220,15 +239,14 @@ preamble
220
239
  end
221
240
 
222
241
  test 'should accept values containing spaces in attributes string' do
223
- # NOTE there's a tab character before self:
224
- doc = Asciidoctor.load('text', :attributes => 'idprefix idseparator=- note-caption=Note\ to\ self: toc')
242
+ doc = Asciidoctor.load('text', :attributes => %(idprefix idseparator=- note-caption=Note\\ to\\\tself toc))
225
243
  assert doc.attributes.is_a?(Hash)
226
244
  assert doc.attr?('idprefix')
227
245
  assert_equal '', doc.attr('idprefix')
228
246
  assert doc.attr?('idseparator')
229
247
  assert_equal '-', doc.attr('idseparator')
230
248
  assert doc.attr?('note-caption')
231
- assert_equal "Note to self:", doc.attr('note-caption')
249
+ assert_equal "Note to\tself", doc.attr('note-caption')
232
250
  end
233
251
 
234
252
  test 'should accept attributes as empty string' do
@@ -343,6 +361,33 @@ preamble
343
361
  assert_equal 1, section_1.lineno
344
362
  end
345
363
 
364
+ test 'should assign correct source location if section occurs on last line of input' do
365
+ input = <<-EOS
366
+ = Document Title
367
+
368
+ == Section A
369
+
370
+ content
371
+
372
+ == Section B
373
+ EOS
374
+
375
+ doc = document_from_string input, :sourcemap => true
376
+ assert_equal [1, 3, 7], (doc.find_by :context => :section).map(&:lineno)
377
+ end
378
+
379
+ test 'should allow sourcemap option on document to be modified' do
380
+ doc = Asciidoctor.load_file fixture_path('sample.asciidoc'), :parse => false
381
+ doc.sourcemap = true
382
+ doc = doc.parse
383
+
384
+ section_1 = doc.sections[0]
385
+ assert_equal 'Section A', section_1.title
386
+ refute_nil section_1.source_location
387
+ assert_equal 'sample.asciidoc', section_1.file
388
+ assert_equal 10, section_1.lineno
389
+ end
390
+
346
391
  test 'find_by should return Array of blocks anywhere in document tree that match criteria' do
347
392
  input = <<-EOS
348
393
  = Document Title
@@ -562,7 +607,7 @@ text
562
607
  assert_css 'html:root > head > link[rel="stylesheet"][href^="https://fonts.googleapis.com"]', output, 1
563
608
  assert_css 'html:root > head > link[rel="stylesheet"][href="./asciidoctor.css"]', output, 0
564
609
  stylenode = xmlnodes_at_css 'html:root > head > style', output, 1
565
- styles = stylenode.first.content
610
+ styles = stylenode.content
566
611
  assert !styles.nil?
567
612
  assert !styles.strip.empty?
568
613
  end
@@ -598,7 +643,7 @@ text
598
643
  :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'linkcss!' => ''}
599
644
  assert_css 'html:root > head > style', output, 1
600
645
  stylenode = xmlnodes_at_css 'html:root > head > style', output, 1
601
- styles = stylenode.first.content
646
+ styles = stylenode.content
602
647
  assert !styles.nil?
603
648
  assert !styles.strip.empty?
604
649
  end
@@ -646,7 +691,7 @@ text
646
691
  output = Asciidoctor.convert_file sample_input_path, :header_footer => true, :safe => Asciidoctor::SafeMode::SAFE, :to_file => false,
647
692
  :attributes => {'stylesheet' => 'custom.css', 'stylesdir' => './stylesheets', 'linkcss!' => ''}
648
693
  stylenode = xmlnodes_at_css 'html:root > head > style', output, 1
649
- styles = stylenode.first.content
694
+ styles = stylenode.content
650
695
  assert !styles.nil?
651
696
  assert !styles.strip.empty?
652
697
  end
@@ -657,7 +702,7 @@ text
657
702
  begin
658
703
  Asciidoctor.convert_file sample_input_path
659
704
  assert File.exist?(sample_output_path)
660
- output = File.read(sample_output_path)
705
+ output = IO.read(sample_output_path)
661
706
  assert !output.empty?
662
707
  assert_xpath '/html', output, 1
663
708
  assert_xpath '/html/head', output, 1
@@ -675,7 +720,7 @@ text
675
720
  begin
676
721
  Asciidoctor.convert_file sample_input_path, :to_file => sample_output_path
677
722
  assert File.exist?(sample_output_path)
678
- output = File.read(sample_output_path)
723
+ output = IO.read(sample_output_path)
679
724
  assert !output.empty?
680
725
  assert_xpath '/html', output, 1
681
726
  assert_xpath '/html/head', output, 1
@@ -694,7 +739,7 @@ text
694
739
  begin
695
740
  Asciidoctor.convert_file sample_input_path, :to_file => 'result.html', :base_dir => fixture_dir
696
741
  assert File.exist?(sample_output_path)
697
- output = File.read(sample_output_path)
742
+ output = IO.read(sample_output_path)
698
743
  assert !output.empty?
699
744
  assert_xpath '/html', output, 1
700
745
  assert_xpath '/html/head', output, 1
@@ -1001,14 +1046,32 @@ text
1001
1046
  assert_css 'copyright', output, 0
1002
1047
  end
1003
1048
 
1004
- test 'should apply explicit substitutions to docinfo files' do
1005
- sample_input_path = fixture_path('subs.adoc')
1049
+ test 'should substitute attributes in docinfo files by default' do
1050
+ sample_input_path = fixture_path 'subs.adoc'
1051
+ output, warnings = redirect_streams do |_, err|
1052
+ output = Asciidoctor.convert_file sample_input_path,
1053
+ :to_file => false,
1054
+ :header_footer => true,
1055
+ :safe => :server,
1056
+ :attributes => { 'docinfo' => '', 'bootstrap-version' => nil, 'linkcss' => '', 'attribute-missing' => 'drop-line' }
1057
+ [output, err.string]
1058
+ end
1059
+ refute output.empty?
1060
+ assert_css 'script', output, 0
1061
+ assert_xpath %(//meta[@name="copyright"][@content="(C) OpenDevise"]), output, 1
1062
+ assert_includes warnings, 'dropping line containing reference to missing attribute'
1063
+ end
1006
1064
 
1007
- output = Asciidoctor.convert_file sample_input_path, :to_file => false,
1008
- :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo' => '', 'docinfosubs' => 'attributes,replacements', 'linkcss' => ''}
1009
- assert !output.empty?
1065
+ test 'should apply explicit substitutions to docinfo files' do
1066
+ sample_input_path = fixture_path 'subs.adoc'
1067
+ output = Asciidoctor.convert_file sample_input_path,
1068
+ :to_file => false,
1069
+ :header_footer => true,
1070
+ :safe => :server,
1071
+ :attributes => { 'docinfo' => '', 'docinfosubs' => 'attributes,replacements', 'linkcss' => '' }
1072
+ refute output.empty?
1010
1073
  assert_css 'script[src="bootstrap.3.2.0.min.js"]', output, 1
1011
- assert_xpath %(//meta[@name="copyright"][@content="#{entity 169} OpenDevise"]), output, 1
1074
+ assert_xpath %(//meta[@name="copyright"][@content="#{decode_char 169} OpenDevise"]), output, 1
1012
1075
  end
1013
1076
  end
1014
1077
 
@@ -1063,6 +1126,19 @@ text
1063
1126
  assert converter.respond_to? element
1064
1127
  end
1065
1128
  end
1129
+
1130
+ test 'should add favicon if favicon attribute is set' do
1131
+ {
1132
+ '' => %w(favicon.ico image/x-icon),
1133
+ '/favicon.ico' => %w(/favicon.ico image/x-icon),
1134
+ '/img/favicon.png' => %w(/img/favicon.png image/png)
1135
+ }.each {|val, (href, type)|
1136
+ result = render_string %(= Untitled), :attributes => { 'favicon' => val }
1137
+ assert_css 'link[rel="shortcut icon"]', result, 1
1138
+ assert_css %(link[rel="shortcut icon"][href="#{href}"]), result, 1
1139
+ assert_css %(link[rel="shortcut icon"][type="#{type}"]), result, 1
1140
+ }
1141
+ end
1066
1142
  end
1067
1143
 
1068
1144
  context 'Structure' do
@@ -1074,6 +1150,50 @@ text
1074
1150
  assert_nil doc.header
1075
1151
  end
1076
1152
 
1153
+ test 'should enable compat mode for document with legacy doctitle' do
1154
+ input = <<-EOS
1155
+ Document Title
1156
+ ==============
1157
+
1158
+ +content+
1159
+ EOS
1160
+
1161
+ doc = document_from_string input
1162
+ assert(doc.attr? 'compat-mode')
1163
+ result = doc.convert
1164
+ assert_xpath '//code[text()="content"]', result, 1
1165
+ end
1166
+
1167
+ test 'should not enable compat mode for document with legacy doctitle if compat mode disable by header' do
1168
+ input = <<-EOS
1169
+ Document Title
1170
+ ==============
1171
+ :compat-mode!:
1172
+
1173
+ +content+
1174
+ EOS
1175
+
1176
+ doc = document_from_string input
1177
+ assert_nil(doc.attr 'compat-mode')
1178
+ result = doc.convert
1179
+ assert_xpath '//code[text()="content"]', result, 0
1180
+ end
1181
+
1182
+ test 'should not enable compat mode for document with legacy doctitle if compat mode is locked by API' do
1183
+ input = <<-EOS
1184
+ Document Title
1185
+ ==============
1186
+
1187
+ +content+
1188
+ EOS
1189
+
1190
+ doc = document_from_string input, :attributes => { 'compat-mode' => nil }
1191
+ assert(doc.attribute_locked? 'compat-mode')
1192
+ assert_nil(doc.attr 'compat-mode')
1193
+ result = doc.convert
1194
+ assert_xpath '//code[text()="content"]', result, 0
1195
+ end
1196
+
1077
1197
  test 'title partition API with default separator' do
1078
1198
  title = Asciidoctor::Document::Title.new 'Main Title: And More: Subtitle'
1079
1199
  assert_equal 'Main Title: And More', title.main
@@ -1119,6 +1239,23 @@ content
1119
1239
  assert_equal 'Subtitle', title.subtitle
1120
1240
  end
1121
1241
 
1242
+ test 'should not honor custom separator for doctitle if attribute is locked by API' do
1243
+ input = <<-EOS
1244
+ [separator=::]
1245
+ = Main Title - *Subtitle*
1246
+ Author Name
1247
+
1248
+ content
1249
+ EOS
1250
+
1251
+ doc = document_from_string input, :attributes => { 'title-separator' => ' -' }
1252
+ title = doc.doctitle :partition => true, :sanitize => true
1253
+ assert title.subtitle?
1254
+ assert title.sanitized?
1255
+ assert_equal 'Main Title', title.main
1256
+ assert_equal 'Subtitle', title.subtitle
1257
+ end
1258
+
1122
1259
  test 'document with doctitle defined as attribute entry' do
1123
1260
  input = <<-EOS
1124
1261
  :doctitle: Document Title
@@ -1251,7 +1388,7 @@ content
1251
1388
 
1252
1389
  output = render_string input
1253
1390
  assert_xpath '/html/head/title[text()="Document Title"]', output, 1
1254
- nodes = xmlnodes_at_xpath('//*[@id="header"]/h1', output, 1)
1391
+ nodes = xmlnodes_at_xpath('//*[@id="header"]/h1', output)
1255
1392
  assert_equal 1, nodes.size
1256
1393
  assert_match('<h1><strong>Document</strong> <span class="image"><img src="logo.png" alt="logo"></span> <em>Title</em> <span class="image"><img src="another-logo.png" alt="another logo"></span></h1>', output)
1257
1394
  end
@@ -1404,6 +1541,18 @@ content
1404
1541
  assert_xpath '//articleinfo/authorinitials[text() = "DW"]', output, 1
1405
1542
  end
1406
1543
 
1544
+ test 'should sanitize content of HTML meta authors tag' do
1545
+ input = <<-EOS
1546
+ = Document Title
1547
+ :author: pass:n[http://example.org/community/team.html[Ze *Product* team]]
1548
+
1549
+ content
1550
+ EOS
1551
+
1552
+ output = render_string input
1553
+ assert_xpath '//meta[@name="author"][@content="Ze Product team"]', output, 1
1554
+ end
1555
+
1407
1556
  test 'should include multiple authors in HTML output' do
1408
1557
  input = <<-EOS
1409
1558
  = Document Title
@@ -1564,11 +1713,11 @@ finally a reference to the second footnote footnoteref:[note2].
1564
1713
  assert_css '#footnotes .footnote', output, 2
1565
1714
  assert_css '#footnotes .footnote#_footnote_1', output, 1
1566
1715
  assert_xpath '//div[@id="footnotes"]/div[@id="_footnote_1"]/a[@href="#_footnoteref_1"][text()="1"]', output, 1
1567
- text = xmlnodes_at_xpath '//div[@id="footnotes"]/div[@id="_footnote_1"]/text()', output, 1
1716
+ text = xmlnodes_at_xpath '//div[@id="footnotes"]/div[@id="_footnote_1"]/text()', output
1568
1717
  assert_equal '. An example footnote.', text.text.strip
1569
1718
  assert_css '#footnotes .footnote#_footnote_2', output, 1
1570
1719
  assert_xpath '//div[@id="footnotes"]/div[@id="_footnote_2"]/a[@href="#_footnoteref_2"][text()="2"]', output, 1
1571
- text = xmlnodes_at_xpath '//div[@id="footnotes"]/div[@id="_footnote_2"]/text()', output, 1
1720
+ text = xmlnodes_at_xpath '//div[@id="footnotes"]/div[@id="_footnote_2"]/text()', output
1572
1721
  assert_equal '. Second footnote.', text.text.strip
1573
1722
  end
1574
1723
 
@@ -1582,7 +1731,7 @@ Text that has supporting information{empty}footnote:[An example footnote.].
1582
1731
  assert_css '#footnotes .footnote', output, 1
1583
1732
  assert_css '#footnotes .footnote#_footnote_1', output, 1
1584
1733
  assert_xpath '/div[@id="footnotes"]/div[@id="_footnote_1"]/a[@href="#_footnoteref_1"][text()="1"]', output, 1
1585
- text = xmlnodes_at_xpath '/div[@id="footnotes"]/div[@id="_footnote_1"]/text()', output, 1
1734
+ text = xmlnodes_at_xpath '/div[@id="footnotes"]/div[@id="_footnote_1"]/text()', output
1586
1735
  assert_equal '. An example footnote.', text.text.strip
1587
1736
  end
1588
1737
 
@@ -1596,6 +1745,30 @@ Text that has supporting information{empty}footnote:[An example footnote.].
1596
1745
  end
1597
1746
  end
1598
1747
 
1748
+ context 'Catalog' do
1749
+ test 'document catalog is aliased as references' do
1750
+ input = <<-EOS
1751
+ = Document Title
1752
+
1753
+ == Section A
1754
+
1755
+ content
1756
+
1757
+ == Section B
1758
+
1759
+ content{blank}footnote:[commentary]
1760
+ EOS
1761
+
1762
+ doc = document_from_string input
1763
+ refute_nil doc.catalog
1764
+ assert_equal [:footnotes, :ids, :images, :includes, :indexterms, :links, :refs].to_set, doc.catalog.keys.to_set
1765
+ assert_same doc.catalog, doc.references
1766
+ assert_same doc.catalog[:footnotes], doc.references[:footnotes]
1767
+ assert_same doc.catalog[:ids], doc.references[:ids]
1768
+ assert_equal 'Section A', doc.references[:ids]['_section_a']
1769
+ end
1770
+ end
1771
+
1599
1772
  context 'Backends and Doctypes' do
1600
1773
  test 'html5 backend doctype article' do
1601
1774
  result = render_string("= Title\n\nparagraph", :attributes => {'backend' => 'html5'})
@@ -1850,14 +2023,14 @@ section body
1850
2023
  EOS
1851
2024
  result = render_string(input, :keep_namespaces => true, :attributes => {'backend' => 'docbook5'})
1852
2025
  assert_xpath '/xmlns:article', result, 1
1853
- doc = xmlnodes_at_xpath('/xmlns:article', result, 1).first
2026
+ doc = xmlnodes_at_xpath('/xmlns:article', result, 1)
1854
2027
  assert_equal 'http://docbook.org/ns/docbook', doc.namespaces['xmlns']
1855
2028
  assert_equal 'http://www.w3.org/1999/xlink', doc.namespaces['xmlns:xl']
1856
2029
  assert_xpath '/xmlns:article[@version="5.0"]', result, 1
1857
2030
  assert_xpath '/xmlns:article/xmlns:info/xmlns:title[text() = "Title"]', result, 1
1858
2031
  assert_xpath '/xmlns:article/xmlns:simpara[text() = "preamble"]', result, 1
1859
2032
  assert_xpath '/xmlns:article/xmlns:section', result, 1
1860
- section = xmlnodes_at_xpath('/xmlns:article/xmlns:section', result, 1).first
2033
+ section = xmlnodes_at_xpath('/xmlns:article/xmlns:section', result, 1)
1861
2034
  # nokogiri can't make up its mind
1862
2035
  id_attr = section.attribute('id') || section.attribute('xml:id')
1863
2036
  refute_nil id_attr
@@ -1884,7 +2057,7 @@ section body
1884
2057
  EOS
1885
2058
  result = render_string(input, :keep_namespaces => true, :attributes => {'backend' => 'docbook5', 'doctype' => 'manpage'})
1886
2059
  assert_xpath '/xmlns:refentry', result, 1
1887
- doc = xmlnodes_at_xpath('/xmlns:refentry', result, 1).first
2060
+ doc = xmlnodes_at_xpath('/xmlns:refentry', result, 1)
1888
2061
  assert_equal 'http://docbook.org/ns/docbook', doc.namespaces['xmlns']
1889
2062
  assert_equal 'http://www.w3.org/1999/xlink', doc.namespaces['xmlns:xl']
1890
2063
  assert_xpath '/xmlns:refentry[@version="5.0"]', result, 1
@@ -1896,7 +2069,7 @@ section body
1896
2069
  assert_xpath '/xmlns:refentry/xmlns:refsynopsisdiv', result, 1
1897
2070
  assert_xpath '/xmlns:refentry/xmlns:refsynopsisdiv/xmlns:simpara[text() = "some text"]', result, 1
1898
2071
  assert_xpath '/xmlns:refentry/xmlns:refsection', result, 1
1899
- section = xmlnodes_at_xpath('/xmlns:refentry/xmlns:refsection', result, 1).first
2072
+ section = xmlnodes_at_xpath('/xmlns:refentry/xmlns:refsection', result, 1)
1900
2073
  # nokogiri can't make up its mind
1901
2074
  id_attr = section.attribute('id') || section.attribute('xml:id')
1902
2075
  refute_nil id_attr
@@ -1918,14 +2091,14 @@ chapter body
1918
2091
  EOS
1919
2092
  result = render_string(input, :keep_namespaces => true, :attributes => {'backend' => 'docbook5', 'doctype' => 'book'})
1920
2093
  assert_xpath '/xmlns:book', result, 1
1921
- doc = xmlnodes_at_xpath('/xmlns:book', result, 1).first
2094
+ doc = xmlnodes_at_xpath('/xmlns:book', result, 1)
1922
2095
  assert_equal 'http://docbook.org/ns/docbook', doc.namespaces['xmlns']
1923
2096
  assert_equal 'http://www.w3.org/1999/xlink', doc.namespaces['xmlns:xl']
1924
2097
  assert_xpath '/xmlns:book[@version="5.0"]', result, 1
1925
2098
  assert_xpath '/xmlns:book/xmlns:info/xmlns:title[text() = "Title"]', result, 1
1926
2099
  assert_xpath '/xmlns:book/xmlns:preface/xmlns:simpara[text() = "preamble"]', result, 1
1927
2100
  assert_xpath '/xmlns:book/xmlns:chapter', result, 1
1928
- chapter = xmlnodes_at_xpath('/xmlns:book/xmlns:chapter', result, 1).first
2101
+ chapter = xmlnodes_at_xpath('/xmlns:book/xmlns:chapter', result, 1)
1929
2102
  # nokogiri can't make up its mind
1930
2103
  id_attr = chapter.attribute('id') || chapter.attribute('xml:id')
1931
2104
  refute_nil id_attr
@@ -1934,6 +2107,28 @@ chapter body
1934
2107
  assert_equal '_first_chapter', id_attr.value
1935
2108
  end
1936
2109
 
2110
+ test 'adds a front and back cover image to DocBook 5 when doctype is book' do
2111
+ input = <<-EOS
2112
+ = Title
2113
+ :doctype: book
2114
+ :imagesdir: images
2115
+ :front-cover-image: image:front-cover.jpg[scaledwidth=210mm]
2116
+ :back-cover-image: image:back-cover.jpg[scaledwidth=210mm]
2117
+
2118
+ preamble
2119
+
2120
+ == First Chapter
2121
+
2122
+ chapter body
2123
+ EOS
2124
+
2125
+ result = render_string input, :attributes => {'backend' => 'docbook5'}
2126
+ assert_xpath '//info/cover[@role="front"]', result, 1
2127
+ assert_xpath '//info/cover[@role="front"]//imagedata[@fileref="images/front-cover.jpg"]', result, 1
2128
+ assert_xpath '//info/cover[@role="back"]', result, 1
2129
+ assert_xpath '//info/cover[@role="back"]//imagedata[@fileref="images/back-cover.jpg"]', result, 1
2130
+ end
2131
+
1937
2132
  test 'should be able to set backend using :backend option key' do
1938
2133
  doc = empty_document :backend => 'html5'
1939
2134
  assert_equal 'html5', doc.attributes['backend']
@@ -2115,7 +2310,7 @@ asciidoctor - converts AsciiDoc source files to HTML, DocBook and other formats
2115
2310
  *asciidoctor* ['OPTION']... 'FILE'..
2116
2311
  EOS
2117
2312
 
2118
- output = render_string input, :header_footer => false
2313
+ output = render_embedded_string input
2119
2314
  assert_xpath '/h1[text()="asciidoctor(1) Manual Page"]', output, 1
2120
2315
  assert_xpath '/h1/following-sibling::h2[text()="NAME"]', output, 1
2121
2316
  assert_xpath '/h2[text()="NAME"]/following-sibling::*[@class="sectionbody"]', output, 1
@@ -2141,20 +2336,35 @@ asciidoctor - converts AsciiDoc source files to HTML, DocBook and other formats
2141
2336
  test 'keeps naughty relative paths from getting outside' do
2142
2337
  naughty_path = 'safe/ok/../../../../../etc/passwd'
2143
2338
  doc = empty_document
2144
- secure_path = doc.normalize_asset_path(naughty_path)
2339
+ secure_path = redirect_streams { doc.normalize_asset_path(naughty_path) }
2145
2340
  assert naughty_path != secure_path
2146
2341
  assert_match(/^#{doc.base_dir}/, secure_path)
2147
2342
  end
2148
2343
 
2149
- test 'should raise an exception when a converter cannot be resolved' do
2344
+ test 'should raise an exception when a converter cannot be resolved before conversion' do
2345
+ input = <<-EOS
2346
+ = Document Title
2347
+
2348
+ text
2349
+ EOS
2350
+ exception = assert_raises NotImplementedError do
2351
+ Asciidoctor.convert input, :backend => 'unknownBackend'
2352
+ end
2353
+ assert_includes exception.message, 'missing converter for backend \'unknownBackend\''
2354
+ end
2355
+
2356
+ test 'should raise an exception when a converter cannot be resolved while parsing' do
2150
2357
  input = <<-EOS
2151
2358
  = Document Title
2359
+
2360
+ == A _Big_ Section
2361
+
2152
2362
  text
2153
2363
  EOS
2154
- exception = assert_raises RuntimeError do
2155
- Asciidoctor.render(input, :backend => "unknownBackend")
2364
+ exception = assert_raises NotImplementedError do
2365
+ Asciidoctor.convert input, :backend => 'unknownBackend'
2156
2366
  end
2157
- assert_match(/missing converter for backend 'unknownBackend'/, exception.message)
2367
+ assert_includes exception.message, 'missing converter for backend \'unknownBackend\''
2158
2368
  end
2159
2369
  end
2160
2370