asciidoctor 0.1.4 → 1.5.0

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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +209 -25
  3. data/{LICENSE → LICENSE.adoc} +4 -3
  4. data/README.adoc +392 -395
  5. data/Rakefile +94 -137
  6. data/benchmark/benchmark.rb +127 -0
  7. data/benchmark/sample-data/mdbasics.adoc +334 -0
  8. data/bin/asciidoctor +5 -8
  9. data/bin/asciidoctor-safe +4 -8
  10. data/compat/asciidoc.conf +78 -11
  11. data/compat/font-awesome-3-compat.css +397 -0
  12. data/data/stylesheets/asciidoctor-default.css +399 -0
  13. data/data/stylesheets/coderay-asciidoctor.css +89 -0
  14. data/features/open_block.feature +92 -0
  15. data/features/pass_block.feature +66 -0
  16. data/features/step_definitions.rb +42 -0
  17. data/features/text_formatting.feature +55 -0
  18. data/features/xref.feature +116 -0
  19. data/lib/asciidoctor.rb +1155 -605
  20. data/lib/asciidoctor/abstract_block.rb +157 -71
  21. data/lib/asciidoctor/abstract_node.rb +150 -93
  22. data/lib/asciidoctor/attribute_list.rb +85 -90
  23. data/lib/asciidoctor/block.rb +51 -24
  24. data/lib/asciidoctor/callouts.rb +4 -7
  25. data/lib/asciidoctor/cli.rb +3 -0
  26. data/lib/asciidoctor/cli/invoker.rb +86 -76
  27. data/lib/asciidoctor/cli/options.rb +111 -61
  28. data/lib/asciidoctor/converter.rb +232 -0
  29. data/lib/asciidoctor/converter/base.rb +58 -0
  30. data/lib/asciidoctor/converter/composite.rb +66 -0
  31. data/lib/asciidoctor/converter/docbook45.rb +94 -0
  32. data/lib/asciidoctor/converter/docbook5.rb +684 -0
  33. data/lib/asciidoctor/converter/factory.rb +225 -0
  34. data/lib/asciidoctor/converter/html5.rb +1081 -0
  35. data/lib/asciidoctor/converter/template.rb +296 -0
  36. data/lib/asciidoctor/core_ext.rb +7 -0
  37. data/lib/asciidoctor/core_ext/object/nil_or_empty.rb +23 -0
  38. data/lib/asciidoctor/core_ext/string/chr.rb +6 -0
  39. data/lib/asciidoctor/core_ext/symbol/length.rb +6 -0
  40. data/lib/asciidoctor/document.rb +590 -304
  41. data/lib/asciidoctor/extensions.rb +1100 -308
  42. data/lib/asciidoctor/helpers.rb +109 -46
  43. data/lib/asciidoctor/inline.rb +16 -9
  44. data/lib/asciidoctor/list.rb +23 -15
  45. data/lib/asciidoctor/opal_ext.rb +4 -0
  46. data/lib/asciidoctor/opal_ext/comparable.rb +38 -0
  47. data/lib/asciidoctor/opal_ext/dir.rb +13 -0
  48. data/lib/asciidoctor/opal_ext/error.rb +2 -0
  49. data/lib/asciidoctor/opal_ext/file.rb +125 -0
  50. data/lib/asciidoctor/{lexer.rb → parser.rb} +646 -455
  51. data/lib/asciidoctor/path_resolver.rb +141 -77
  52. data/lib/asciidoctor/reader.rb +257 -187
  53. data/lib/asciidoctor/section.rb +12 -16
  54. data/lib/asciidoctor/stylesheets.rb +91 -0
  55. data/lib/asciidoctor/substitutors.rb +1548 -0
  56. data/lib/asciidoctor/table.rb +73 -57
  57. data/lib/asciidoctor/timings.rb +39 -0
  58. data/lib/asciidoctor/version.rb +1 -1
  59. data/man/asciidoctor.1 +22 -14
  60. data/man/asciidoctor.adoc +18 -10
  61. data/test/attributes_test.rb +314 -14
  62. data/test/blocks_test.rb +763 -118
  63. data/test/converter_test.rb +352 -0
  64. data/test/document_test.rb +518 -199
  65. data/test/extensions_test.rb +273 -103
  66. data/test/fixtures/asciidoc_index.txt +27 -13
  67. data/test/fixtures/basic-docinfo.xml +1 -1
  68. data/test/fixtures/chapter-a.adoc +3 -0
  69. data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +6 -0
  70. data/test/fixtures/docinfo.xml +1 -1
  71. data/test/fixtures/include-file.asciidoc +2 -0
  72. data/test/fixtures/master.adoc +5 -0
  73. data/test/invoker_test.rb +173 -61
  74. data/test/links_test.rb +97 -21
  75. data/test/lists_test.rb +181 -22
  76. data/test/options_test.rb +86 -2
  77. data/test/paragraphs_test.rb +47 -5
  78. data/test/{lexer_test.rb → parser_test.rb} +128 -57
  79. data/test/paths_test.rb +36 -1
  80. data/test/preamble_test.rb +25 -17
  81. data/test/reader_test.rb +404 -249
  82. data/test/sections_test.rb +623 -58
  83. data/test/substitutions_test.rb +609 -132
  84. data/test/tables_test.rb +198 -24
  85. data/test/test_helper.rb +101 -31
  86. data/test/text_test.rb +88 -31
  87. metadata +160 -64
  88. data/Gemfile +0 -12
  89. data/Guardfile +0 -18
  90. data/asciidoctor.gemspec +0 -143
  91. data/lib/asciidoctor/backends/_stylesheets.rb +0 -466
  92. data/lib/asciidoctor/backends/base_template.rb +0 -114
  93. data/lib/asciidoctor/backends/docbook45.rb +0 -774
  94. data/lib/asciidoctor/backends/docbook5.rb +0 -103
  95. data/lib/asciidoctor/backends/html5.rb +0 -1214
  96. data/lib/asciidoctor/renderer.rb +0 -259
  97. data/lib/asciidoctor/substituters.rb +0 -1083
  98. data/test/fixtures/asciidoc.txt +0 -105
  99. data/test/fixtures/ascshort.txt +0 -32
  100. data/test/fixtures/list_elements.asciidoc +0 -10
  101. data/test/renderer_test.rb +0 -162
@@ -0,0 +1,352 @@
1
+ # encoding: UTF-8
2
+ unless defined? ASCIIDOCTOR_PROJECT_DIR
3
+ $: << File.dirname(__FILE__); $:.uniq!
4
+ require 'test_helper'
5
+ end
6
+ require 'tilt' unless defined? ::Tilt
7
+
8
+ context 'Converter' do
9
+
10
+ context 'View options' do
11
+ test 'should set Haml format to html5 for html5 backend' do
12
+ doc = Asciidoctor::Document.new [], :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml'), :template_cache => false
13
+ assert doc.converter.is_a?(Asciidoctor::Converter::CompositeConverter)
14
+ selected = doc.converter.find_converter('paragraph')
15
+ assert selected.is_a? Asciidoctor::Converter::TemplateConverter
16
+ assert selected.templates['paragraph'].is_a? Tilt::HamlTemplate
17
+ assert_equal :html5, selected.templates['paragraph'].options[:format]
18
+ end
19
+
20
+ test 'should set Haml format to xhtml for docbook backend' do
21
+ doc = Asciidoctor::Document.new [], :backend => 'docbook45', :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml'), :template_cache => false
22
+ assert doc.converter.is_a?(Asciidoctor::Converter::CompositeConverter)
23
+ selected = doc.converter.find_converter('paragraph')
24
+ assert selected.is_a? Asciidoctor::Converter::TemplateConverter
25
+ assert selected.templates['paragraph'].is_a? Tilt::HamlTemplate
26
+ assert_equal :xhtml, selected.templates['paragraph'].options[:format]
27
+ end
28
+
29
+ test 'should set Slim format to html5 for html5 backend' do
30
+ doc = Asciidoctor::Document.new [], :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'slim'), :template_cache => false
31
+ assert doc.converter.is_a?(Asciidoctor::Converter::CompositeConverter)
32
+ selected = doc.converter.find_converter('paragraph')
33
+ assert selected.is_a? Asciidoctor::Converter::TemplateConverter
34
+ assert selected.templates['paragraph'].is_a? Slim::Template
35
+ assert_equal :html5, selected.templates['paragraph'].options[:format]
36
+ end
37
+
38
+ test 'should set Slim format to nil for docbook backend' do
39
+ doc = Asciidoctor::Document.new [], :backend => 'docbook45', :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'slim'), :template_cache => false
40
+ assert doc.converter.is_a?(Asciidoctor::Converter::CompositeConverter)
41
+ selected = doc.converter.find_converter('paragraph')
42
+ assert selected.is_a? Asciidoctor::Converter::TemplateConverter
43
+ assert selected.templates['paragraph'].is_a? Slim::Template
44
+ assert_nil selected.templates['paragraph'].options[:format]
45
+ end
46
+
47
+ test 'should support custom template engine options for known engine' do
48
+ doc = Asciidoctor::Document.new [], :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'slim'), :template_cache => false, :template_engine_options => { :slim => { :pretty => true } }
49
+ assert doc.converter.is_a?(Asciidoctor::Converter::CompositeConverter)
50
+ selected = doc.converter.find_converter('paragraph')
51
+ assert selected.is_a? Asciidoctor::Converter::TemplateConverter
52
+ assert selected.templates['paragraph'].is_a? Slim::Template
53
+ assert_equal true, selected.templates['paragraph'].options[:pretty]
54
+ end
55
+
56
+ test 'should support custom template engine options' do
57
+ doc = Asciidoctor::Document.new [], :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'slim'), :template_cache => false, :template_engine_options => { :slim => { :pretty => true } }
58
+ assert doc.converter.is_a?(Asciidoctor::Converter::CompositeConverter)
59
+ selected = doc.converter.find_converter('paragraph')
60
+ assert selected.is_a? Asciidoctor::Converter::TemplateConverter
61
+ assert selected.templates['paragraph'].is_a? Slim::Template
62
+ assert_equal false, selected.templates['paragraph'].options[:sort_attrs]
63
+ assert_equal true, selected.templates['paragraph'].options[:pretty]
64
+ end
65
+ end
66
+
67
+ context 'Custom backends' do
68
+ test 'should load Haml templates for default backend' do
69
+ doc = Asciidoctor::Document.new [], :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml'), :template_cache => false
70
+ assert doc.converter.is_a?(Asciidoctor::Converter::CompositeConverter)
71
+ ['paragraph', 'sidebar'].each do |node_name|
72
+ selected = doc.converter.find_converter node_name
73
+ assert selected.is_a? Asciidoctor::Converter::TemplateConverter
74
+ assert selected.templates[node_name].is_a? Tilt::HamlTemplate
75
+ assert_equal %(block_#{node_name}.html.haml), File.basename(selected.templates[node_name].file)
76
+ end
77
+ end
78
+
79
+ test 'should set outfilesuffix according to backend info' do
80
+ doc = Asciidoctor.load 'content'
81
+ doc.render
82
+ assert_equal '.html', doc.attributes['outfilesuffix']
83
+
84
+ doc = Asciidoctor.load 'content', :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml'), :template_cache => false
85
+ doc.render
86
+ assert_equal '.html', doc.attributes['outfilesuffix']
87
+ end
88
+
89
+ test 'should not override outfilesuffix attribute if locked' do
90
+ doc = Asciidoctor.load 'content', :attributes => {'outfilesuffix' => '.foo'}
91
+ doc.render
92
+ assert_equal '.foo', doc.attributes['outfilesuffix']
93
+
94
+ doc = Asciidoctor.load 'content', :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml'), :template_cache => false, :attributes => {'outfilesuffix' => '.foo'}
95
+ doc.render
96
+ assert_equal '.foo', doc.attributes['outfilesuffix']
97
+ end
98
+
99
+ test 'should load Haml templates for docbook45 backend' do
100
+ doc = Asciidoctor::Document.new [], :backend => 'docbook45', :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml'), :template_cache => false
101
+ assert doc.converter.is_a?(Asciidoctor::Converter::CompositeConverter)
102
+ ['paragraph'].each do |node_name|
103
+ selected = doc.converter.find_converter node_name
104
+ assert selected.is_a? Asciidoctor::Converter::TemplateConverter
105
+ assert selected.templates[node_name].is_a? Tilt::HamlTemplate
106
+ assert_equal %(block_#{node_name}.xml.haml), File.basename(selected.templates[node_name].file)
107
+ end
108
+ end
109
+
110
+ test 'should use Haml templates in place of built-in templates' do
111
+ input = <<-EOS
112
+ = Document Title
113
+ Author Name
114
+
115
+ == Section One
116
+
117
+ Sample paragraph
118
+
119
+ .Related
120
+ ****
121
+ Sidebar content
122
+ ****
123
+ EOS
124
+
125
+ output = render_embedded_string input, :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml'), :template_cache => false
126
+ assert_xpath '/*[@class="sect1"]/*[@class="sectionbody"]/p', output, 1
127
+ assert_xpath '//aside', output, 1
128
+ assert_xpath '/*[@class="sect1"]/*[@class="sectionbody"]/p/following-sibling::aside', output, 1
129
+ assert_xpath '//aside/header/h1[text()="Related"]', output, 1
130
+ assert_xpath '//aside/header/following-sibling::p[text()="Sidebar content"]', output, 1
131
+ end
132
+
133
+ test 'should use built-in global cache to cache templates' do
134
+ begin
135
+ # clear out any cache, just to be sure
136
+ Asciidoctor::Converter::TemplateConverter.clear_caches if defined? Asciidoctor::Converter::TemplateConverter
137
+
138
+ template_dir = File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml')
139
+ doc = Asciidoctor::Document.new [], :template_dir => template_dir
140
+ doc.converter
141
+ caches = Asciidoctor::Converter::TemplateConverter.caches
142
+ if defined? ::ThreadSafe::Cache
143
+ assert caches[:templates].is_a?(::ThreadSafe::Cache)
144
+ assert !caches[:templates].empty?
145
+ paragraph_template_before = caches[:templates].values.find {|t| File.basename(t.file) == 'block_paragraph.html.haml' }
146
+ assert !paragraph_template_before.nil?
147
+
148
+ # should use cache
149
+ doc = Asciidoctor::Document.new [], :template_dir => template_dir
150
+ template_converter = doc.converter.find_converter('paragraph')
151
+ paragraph_template_after = template_converter.templates['paragraph']
152
+ assert !paragraph_template_after.nil?
153
+ assert paragraph_template_before.eql?(paragraph_template_after)
154
+
155
+ # should not use cache
156
+ doc = Asciidoctor::Document.new [], :template_dir => template_dir, :template_cache => false
157
+ template_converter = doc.converter.find_converter('paragraph')
158
+ paragraph_template_after = template_converter.templates['paragraph']
159
+ assert !paragraph_template_after.nil?
160
+ assert !paragraph_template_before.eql?(paragraph_template_after)
161
+ else
162
+ assert caches.empty?
163
+ end
164
+ ensure
165
+ # clean up
166
+ Asciidoctor::Converter::TemplateConverter.clear_caches if defined? Asciidoctor::Converter::TemplateConverter
167
+ end
168
+ end
169
+
170
+ test 'should use custom cache to cache templates' do
171
+ template_dir = File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml')
172
+ Asciidoctor::PathResolver.new.system_path(File.join(template_dir, 'html5', 'block_paragraph.html.haml'), nil)
173
+ caches = { :scans => {}, :templates => {} }
174
+ doc = Asciidoctor::Document.new [], :template_dir => template_dir, :template_cache => caches
175
+ doc.converter
176
+ assert !caches[:scans].empty?
177
+ assert !caches[:templates].empty?
178
+ paragraph_template = caches[:templates].values.find {|t| File.basename(t.file) == 'block_paragraph.html.haml' }
179
+ assert !paragraph_template.nil?
180
+ assert paragraph_template.is_a? ::Tilt::HamlTemplate
181
+ end
182
+
183
+ test 'should be able to disable template cache' do
184
+ begin
185
+ # clear out any cache, just to be sure
186
+ Asciidoctor::Converter::TemplateConverter.clear_caches if defined? Asciidoctor::Converter::TemplateConverter
187
+
188
+ doc = Asciidoctor::Document.new [], :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml'),
189
+ :template_cache => false
190
+ doc.converter
191
+ caches = Asciidoctor::Converter::TemplateConverter.caches
192
+ assert caches.empty? || caches[:scans].empty?
193
+ assert caches.empty? || caches[:templates].empty?
194
+ ensure
195
+ # clean up
196
+ Asciidoctor::Converter::TemplateConverter.clear_caches if defined? Asciidoctor::Converter::TemplateConverter
197
+ end
198
+ end
199
+
200
+ test 'should load ERB templates using ERBTemplate if eruby is not set' do
201
+ doc = Asciidoctor::Document.new [], :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'erb'), :template_cache => false
202
+ assert doc.converter.is_a?(Asciidoctor::Converter::CompositeConverter)
203
+ ['paragraph'].each do |node_name|
204
+ selected = doc.converter.find_converter node_name
205
+ assert selected.is_a? Asciidoctor::Converter::TemplateConverter
206
+ template = selected.templates[node_name]
207
+ assert template.is_a? Tilt::ERBTemplate
208
+ assert !(template.is_a? Tilt::ErubisTemplate)
209
+ assert template.instance_variable_get('@engine').is_a? ::ERB
210
+ assert_equal %(block_#{node_name}.html.erb), File.basename(selected.templates[node_name].file)
211
+ end
212
+ end
213
+
214
+ test 'should load ERB templates using ErubisTemplate if eruby is set to erubis' do
215
+ doc = Asciidoctor::Document.new [], :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'erb'), :template_cache => false, :eruby => 'erubis'
216
+ assert doc.converter.is_a?(Asciidoctor::Converter::CompositeConverter)
217
+ ['paragraph'].each do |node_name|
218
+ selected = doc.converter.find_converter node_name
219
+ assert selected.is_a? Asciidoctor::Converter::TemplateConverter
220
+ template = selected.templates[node_name]
221
+ assert template.is_a? Tilt::ERBTemplate
222
+ assert template.is_a? Tilt::ErubisTemplate
223
+ assert template.instance_variable_get('@engine').is_a? ::Erubis::FastEruby
224
+ assert_equal %(block_#{node_name}.html.erb), File.basename(selected.templates[node_name].file)
225
+ end
226
+ end
227
+
228
+ test 'should load Slim templates for default backend' do
229
+ doc = Asciidoctor::Document.new [], :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'slim'), :template_cache => false
230
+ assert doc.converter.is_a?(Asciidoctor::Converter::CompositeConverter)
231
+ ['paragraph', 'sidebar'].each do |node_name|
232
+ selected = doc.converter.find_converter node_name
233
+ assert selected.is_a? Asciidoctor::Converter::TemplateConverter
234
+ assert selected.templates[node_name].is_a? Slim::Template
235
+ assert_equal %(block_#{node_name}.html.slim), File.basename(selected.templates[node_name].file)
236
+ end
237
+ end
238
+
239
+ test 'should load Slim templates for docbook45 backend' do
240
+ doc = Asciidoctor::Document.new [], :backend => 'docbook45', :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'slim'), :template_cache => false
241
+ assert doc.converter.is_a?(Asciidoctor::Converter::CompositeConverter)
242
+ ['paragraph'].each do |node_name|
243
+ selected = doc.converter.find_converter node_name
244
+ assert selected.is_a? Asciidoctor::Converter::TemplateConverter
245
+ assert selected.templates[node_name].is_a? Slim::Template
246
+ assert_equal %(block_#{node_name}.xml.slim), File.basename(selected.templates[node_name].file)
247
+ end
248
+ end
249
+
250
+ test 'should use Slim templates in place of built-in templates' do
251
+ input = <<-EOS
252
+ = Document Title
253
+ Author Name
254
+
255
+ == Section One
256
+
257
+ Sample paragraph
258
+
259
+ .Related
260
+ ****
261
+ Sidebar content
262
+ ****
263
+ EOS
264
+
265
+ output = render_embedded_string input, :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'slim'), :template_cache => false
266
+ assert_xpath '/*[@class="sect1"]/*[@class="sectionbody"]/p', output, 1
267
+ assert_xpath '//aside', output, 1
268
+ assert_xpath '/*[@class="sect1"]/*[@class="sectionbody"]/p/following-sibling::aside', output, 1
269
+ assert_xpath '//aside/header/h1[text()="Related"]', output, 1
270
+ assert_xpath '//aside/header/following-sibling::p[text()="Sidebar content"]', output, 1
271
+ end
272
+
273
+ test 'should use custom converter if specified' do
274
+ input = <<-EOS
275
+ = Document Title
276
+
277
+ preamble
278
+
279
+ == Section
280
+
281
+ content
282
+ EOS
283
+
284
+ class CustomConverterA
285
+ def initialize backend, opts = {}
286
+ end
287
+
288
+ def convert node, name = nil
289
+ 'document'
290
+ end
291
+
292
+ def self.converts? backend
293
+ true
294
+ end
295
+ end
296
+
297
+ output = render_string input, :converter => CustomConverterA
298
+ assert 'document', output
299
+ end
300
+
301
+ test 'should use converter registered for backend' do
302
+ input = <<-EOS
303
+ content
304
+ EOS
305
+
306
+ begin
307
+ Asciidoctor::Converter::Factory.unregister_all
308
+
309
+ class CustomConverterB
310
+ include Asciidoctor::Converter
311
+ register_for 'foobar'
312
+ def convert node, name = nil
313
+ 'foobar content'
314
+ end
315
+ end
316
+
317
+ converters = Asciidoctor::Converter::Factory.converters
318
+ assert converters.size == 1
319
+ assert converters['foobar'] == CustomConverterB
320
+ output = render_string input, :backend => 'foobar'
321
+ assert 'foobar content', output
322
+ ensure
323
+ Asciidoctor::Converter::Factory.unregister_all
324
+ end
325
+ end
326
+
327
+ test 'should fall back to catch all converter' do
328
+ input = <<-EOS
329
+ content
330
+ EOS
331
+
332
+ begin
333
+ Asciidoctor::Converter::Factory.unregister_all
334
+
335
+ class CustomConverterC
336
+ include Asciidoctor::Converter
337
+ register_for '*'
338
+ def convert node, name = nil
339
+ 'foobaz content'
340
+ end
341
+ end
342
+
343
+ converters = Asciidoctor::Converter::Factory.converters
344
+ assert converters['*'] == CustomConverterC
345
+ output = render_string input, :backend => 'foobaz'
346
+ assert 'foobaz content', output
347
+ ensure
348
+ Asciidoctor::Converter::Factory.unregister_all
349
+ end
350
+ end
351
+ end
352
+ end
@@ -1,4 +1,10 @@
1
- require 'test_helper'
1
+ # encoding: UTF-8
2
+ unless defined? ASCIIDOCTOR_PROJECT_DIR
3
+ $: << File.dirname(__FILE__); $:.uniq!
4
+ require 'test_helper'
5
+ end
6
+
7
+ BUILT_IN_ELEMENTS = %w(admonition audio colist dlist document embedded example floating_title image inline_anchor inline_break inline_button inline_callout inline_footnote inline_image inline_indexterm inline_kbd inline_menu inline_quoted listing literal stem olist open page_break paragraph pass preamble quote section sidebar table thematic_break toc ulist verse video)
2
8
 
3
9
  context 'Document' do
4
10
 
@@ -9,42 +15,46 @@ context 'Document' do
9
15
  assert_equal 'AsciiDoc Home Page', doc.name
10
16
  assert_equal 14, doc.blocks.size
11
17
  assert_equal :preamble, doc.blocks[0].context
12
- assert doc.blocks[1].is_a? ::Asciidoctor::Section
18
+ assert doc.blocks[1].context == :section
19
+
20
+ # verify compat-mode is set when atx-style doctitle is used
21
+ result = doc.blocks[0].convert
22
+ assert_xpath %q(//em[text()="Stuart Rackham"]), result, 1
13
23
  end
14
24
  end
15
25
 
16
26
  context 'Default settings' do
17
27
  test 'safe mode level set to SECURE by default' do
18
- doc = Asciidoctor::Document.new
28
+ doc = empty_document
19
29
  assert_equal Asciidoctor::SafeMode::SECURE, doc.safe
20
30
  end
21
31
 
22
32
  test 'safe mode level set using string' do
23
- doc = Asciidoctor::Document.new [], :safe => 'server'
33
+ doc = empty_document :safe => 'server'
24
34
  assert_equal Asciidoctor::SafeMode::SERVER, doc.safe
25
35
 
26
- doc = Asciidoctor::Document.new [], :safe => 'foo'
36
+ doc = empty_document :safe => 'foo'
27
37
  assert_equal Asciidoctor::SafeMode::SECURE, doc.safe
28
38
  end
29
39
 
30
40
  test 'safe mode level set using symbol' do
31
- doc = Asciidoctor::Document.new [], :safe => :server
41
+ doc = empty_document :safe => :server
32
42
  assert_equal Asciidoctor::SafeMode::SERVER, doc.safe
33
43
 
34
- doc = Asciidoctor::Document.new [], :safe => :foo
44
+ doc = empty_document :safe => :foo
35
45
  assert_equal Asciidoctor::SafeMode::SECURE, doc.safe
36
46
  end
37
47
 
38
48
  test 'safe mode level set using integer' do
39
- doc = Asciidoctor::Document.new [], :safe => 10
49
+ doc = empty_document :safe => 10
40
50
  assert_equal Asciidoctor::SafeMode::SERVER, doc.safe
41
51
 
42
- doc = Asciidoctor::Document.new [], :safe => 100
52
+ doc = empty_document :safe => 100
43
53
  assert_equal 100, doc.safe
44
54
  end
45
55
 
46
56
  test 'safe mode attributes are set on document' do
47
- doc = Asciidoctor::Document.new
57
+ doc = empty_document
48
58
  assert_equal Asciidoctor::SafeMode::SECURE, doc.attr('safe-mode-level')
49
59
  assert_equal 'secure', doc.attr('safe-mode-name')
50
60
  assert doc.attr?('safe-mode-secure')
@@ -59,7 +69,7 @@ context 'Document' do
59
69
  end
60
70
 
61
71
  test 'safe model level cannot be modified' do
62
- doc = Asciidoctor::Document.new
72
+ doc = empty_document
63
73
  begin
64
74
  doc.safe = Asciidoctor::SafeMode::UNSAFE
65
75
  flunk 'safe mode property of Asciidoctor::Document should not be writable!'
@@ -67,21 +77,30 @@ context 'Document' do
67
77
  end
68
78
  end
69
79
 
70
- test 'toc and numbered should be enabled by default for DocBook backend' do
71
- doc = Asciidoctor::Document.new [], :backend => 'docbook'
80
+ test 'toc and sectnums should be enabled by default for DocBook backend' do
81
+ doc = empty_document :backend => 'docbook', :parse => true
72
82
  assert doc.attr?('toc')
73
- assert doc.attr?('numbered')
83
+ assert doc.attr?('sectnums')
74
84
  end
75
85
 
76
- test 'should be able to disable toc and numbered in document header for DocBook backend' do
86
+ test 'should be able to disable toc and sectnums in document header for DocBook backend' do
77
87
  input = <<-EOS
78
88
  = Document Title
79
89
  :toc!:
80
- :numbered!:
90
+ :sectnums!:
81
91
  EOS
82
92
  doc = document_from_string input, :backend => 'docbook'
83
93
  assert !doc.attr?('toc')
84
- assert !doc.attr?('numbered')
94
+ assert !doc.attr?('sectnums')
95
+ end
96
+
97
+ test 'should be able to disable section numbering using numbered attribute in document header for DocBook backend' do
98
+ input = <<-EOS
99
+ = Document Title
100
+ :numbered!:
101
+ EOS
102
+ doc = document_from_string input, :backend => 'docbook'
103
+ assert !doc.attr?('sectnums')
85
104
  end
86
105
  end
87
106
 
@@ -143,12 +162,12 @@ preamble
143
162
 
144
163
  test 'should accept attributes as array' do
145
164
  # NOTE there's a tab character before idseparator
146
- doc = Asciidoctor.load('text', :attributes => %w(toc numbered source-highlighter=coderay idprefix idseparator=-))
165
+ doc = Asciidoctor.load('text', :attributes => %w(toc sectnums source-highlighter=coderay idprefix idseparator=-))
147
166
  assert doc.attributes.is_a?(Hash)
148
167
  assert doc.attr?('toc')
149
168
  assert_equal '', doc.attr('toc')
150
- assert doc.attr?('numbered')
151
- assert_equal '', doc.attr('numbered')
169
+ assert doc.attr?('sectnums')
170
+ assert_equal '', doc.attr('sectnums')
152
171
  assert doc.attr?('source-highlighter')
153
172
  assert_equal 'coderay', doc.attr('source-highlighter')
154
173
  assert doc.attr?('idprefix')
@@ -164,12 +183,12 @@ preamble
164
183
 
165
184
  test 'should accept attributes as string' do
166
185
  # NOTE there's a tab character before idseparator
167
- doc = Asciidoctor.load('text', :attributes => 'toc numbered source-highlighter=coderay idprefix idseparator=-')
186
+ doc = Asciidoctor.load('text', :attributes => 'toc sectnums source-highlighter=coderay idprefix idseparator=-')
168
187
  assert doc.attributes.is_a?(Hash)
169
188
  assert doc.attr?('toc')
170
189
  assert_equal '', doc.attr('toc')
171
- assert doc.attr?('numbered')
172
- assert_equal '', doc.attr('numbered')
190
+ assert doc.attr?('sectnums')
191
+ assert_equal '', doc.attr('sectnums')
173
192
  assert doc.attr?('source-highlighter')
174
193
  assert_equal 'coderay', doc.attr('source-highlighter')
175
194
  assert doc.attr?('idprefix')
@@ -219,13 +238,104 @@ preamble
219
238
  assert doc.attributes.is_a?(Hash)
220
239
  assert doc.attributes.has_key?('toc')
221
240
  end
241
+
242
+ test 'should not modify options argument' do
243
+ options = {
244
+ :safe => Asciidoctor::SafeMode::SAFE
245
+ }
246
+ options.freeze
247
+ sample_input_path = fixture_path('sample.asciidoc')
248
+ begin
249
+ Asciidoctor.load_file sample_input_path, options
250
+ rescue
251
+ flunk %(options argument should not be modified)
252
+ end
253
+ end
254
+
255
+ test 'should not modify attributes Hash argument' do
256
+ attributes = {}
257
+ attributes.freeze
258
+ options = {
259
+ :safe => Asciidoctor::SafeMode::SAFE,
260
+ :attributes => attributes
261
+ }
262
+ sample_input_path = fixture_path('sample.asciidoc')
263
+ begin
264
+ Asciidoctor.load_file sample_input_path, options
265
+ rescue
266
+ flunk %(attributes argument should not be modified)
267
+ end
268
+ end
269
+
270
+ test 'should track file and line information with blocks if sourcemap option is set' do
271
+ doc = Asciidoctor.load_file fixture_path('sample.asciidoc'), :sourcemap => true
272
+
273
+ section_1 = doc.sections[0]
274
+ assert_equal 'Section A', section_1.title
275
+ refute_nil section_1.source_location
276
+ assert_equal 'sample.asciidoc', section_1.file
277
+ assert_equal 10, section_1.lineno
278
+
279
+ section_2 = doc.sections[1]
280
+ assert_equal 'Section B', section_2.title
281
+ refute_nil section_2.source_location
282
+ assert_equal 'sample.asciidoc', section_2.file
283
+ assert_equal 18, section_2.lineno
284
+
285
+ last_block = section_2.blocks[-1]
286
+ assert_equal :ulist, last_block.context
287
+ refute_nil last_block.source_location
288
+ assert_equal 'sample.asciidoc', last_block.file
289
+ assert_equal 23, last_block.lineno
290
+
291
+ doc = Asciidoctor.load_file fixture_path('master.adoc'), :sourcemap => true, :safe => :safe
292
+
293
+ section_1 = doc.sections[0]
294
+ assert_equal 'Chapter A', section_1.title
295
+ refute_nil section_1.source_location
296
+ assert_equal fixture_path('chapter-a.adoc'), section_1.file
297
+ assert_equal 1, section_1.lineno
298
+ end
299
+
300
+ test 'find_by should return Array of blocks that match criteria' do
301
+ input = <<-EOS
302
+ = Document Title
303
+
304
+ preamble
305
+
306
+ == Section A
307
+
308
+ paragraph
309
+
310
+ --
311
+ Exhibit A::
312
+ +
313
+ [#tiger.animal]
314
+ image::tiger.png[Tiger]
315
+ --
316
+
317
+ image::cat.png[Cat]
318
+
319
+ == Section B
320
+
321
+ paragraph
322
+ EOS
323
+
324
+ doc = Asciidoctor.load input
325
+ result = doc.find_by :context => :image
326
+ assert_equal 2, result.size
327
+ assert_equal :image, result[0].context
328
+ assert_equal 'tiger.png', result[0].attr('target')
329
+ assert_equal :image, result[1].context
330
+ assert_equal 'cat.png', result[1].attr('target')
331
+ end
222
332
  end
223
333
 
224
- context 'Render APIs' do
225
- test 'should render document to string' do
334
+ context 'Convert APIs' do
335
+ test 'should convert source document to string when to_file is false' do
226
336
  sample_input_path = fixture_path('sample.asciidoc')
227
337
 
228
- output = Asciidoctor.render_file(sample_input_path, :header_footer => true)
338
+ output = Asciidoctor.convert_file sample_input_path, :header_footer => true, :to_file => false
229
339
  assert !output.empty?
230
340
  assert_xpath '/html', output, 1
231
341
  assert_xpath '/html/head', output, 1
@@ -236,19 +346,19 @@ preamble
236
346
 
237
347
  test 'should accept attributes as array' do
238
348
  sample_input_path = fixture_path('sample.asciidoc')
239
- output = Asciidoctor.render_file(sample_input_path, :attributes => %w(numbered idprefix idseparator=-))
349
+ output = Asciidoctor.convert_file sample_input_path, :attributes => %w(sectnums idprefix idseparator=-), :to_file => false
240
350
  assert_css '#section-a', output, 1
241
351
  end
242
352
 
243
353
  test 'should accept attributes as string' do
244
354
  sample_input_path = fixture_path('sample.asciidoc')
245
- output = Asciidoctor.render_file(sample_input_path, :attributes => 'numbered idprefix idseparator=-')
355
+ output = Asciidoctor.convert_file sample_input_path, :attributes => 'sectnums idprefix idseparator=-', :to_file => false
246
356
  assert_css '#section-a', output, 1
247
357
  end
248
358
 
249
359
  test 'should link to default stylesheet by default when safe mode is SECURE or greater' do
250
360
  sample_input_path = fixture_path('basic.asciidoc')
251
- output = Asciidoctor.render_file(sample_input_path, :header_footer => true)
361
+ output = Asciidoctor.convert_file sample_input_path, :header_footer => true, :to_file => false
252
362
  assert_css 'html:root > head > link[rel="stylesheet"][href="./asciidoctor.css"]', output, 1
253
363
  end
254
364
 
@@ -267,7 +377,7 @@ text
267
377
  assert !styles.strip.empty?
268
378
  end
269
379
 
270
- test 'should link to default stylesheet by default if linkcss is unset in document' do
380
+ test 'should link to default stylesheet by default even if linkcss is unset in document' do
271
381
  input = <<-EOS
272
382
  = Document Title
273
383
  :linkcss!:
@@ -292,8 +402,8 @@ text
292
402
 
293
403
  test 'should embed default stylesheet if safe mode is less than secure and linkcss is unset' do
294
404
  sample_input_path = fixture_path('basic.asciidoc')
295
- output = Asciidoctor.render_file(sample_input_path, :header_footer => true,
296
- :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'linkcss!' => ''})
405
+ output = Asciidoctor.convert_file sample_input_path, :header_footer => true, :to_file => false,
406
+ :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'linkcss!' => ''}
297
407
  assert_css 'html:root > head > style', output, 1
298
408
  stylenode = xmlnodes_at_css 'html:root > head > style', output, 1
299
409
  styles = stylenode.first.content
@@ -336,19 +446,19 @@ text
336
446
 
337
447
  test 'should resolve custom stylesheet to embed relative to stylesdir' do
338
448
  sample_input_path = fixture_path('basic.asciidoc')
339
- output = Asciidoctor.render_file(sample_input_path, :header_footer => true, :safe => Asciidoctor::SafeMode::SAFE,
340
- :attributes => {'stylesheet' => 'custom.css', 'stylesdir' => './stylesheets', 'linkcss!' => ''})
449
+ output = Asciidoctor.convert_file sample_input_path, :header_footer => true, :safe => Asciidoctor::SafeMode::SAFE, :to_file => false,
450
+ :attributes => {'stylesheet' => 'custom.css', 'stylesdir' => './stylesheets', 'linkcss!' => ''}
341
451
  stylenode = xmlnodes_at_css 'html:root > head > style', output, 1
342
452
  styles = stylenode.first.content
343
453
  assert !styles.nil?
344
454
  assert !styles.strip.empty?
345
455
  end
346
456
 
347
- test 'should render document in place' do
457
+ test 'should convert source file and write result to adjacent file by default' do
348
458
  sample_input_path = fixture_path('sample.asciidoc')
349
459
  sample_output_path = fixture_path('sample.html')
350
460
  begin
351
- Asciidoctor.render_file(sample_input_path, :in_place => true)
461
+ Asciidoctor.convert_file sample_input_path
352
462
  assert File.exist?(sample_output_path)
353
463
  output = File.read(sample_output_path)
354
464
  assert !output.empty?
@@ -358,15 +468,15 @@ text
358
468
  assert_xpath '/html/head/title[text() = "Document Title"]', output, 1
359
469
  assert_xpath '/html/body/*[@id="header"]/h1[text() = "Document Title"]', output, 1
360
470
  ensure
361
- FileUtils::rm(sample_output_path)
471
+ FileUtils.rm(sample_output_path)
362
472
  end
363
473
  end
364
474
 
365
- test 'should render document to file' do
475
+ test 'should convert source file and write to specified file' do
366
476
  sample_input_path = fixture_path('sample.asciidoc')
367
477
  sample_output_path = fixture_path('result.html')
368
478
  begin
369
- Asciidoctor.render_file(sample_input_path, :to_file => sample_output_path)
479
+ Asciidoctor.convert_file sample_input_path, :to_file => sample_output_path
370
480
  assert File.exist?(sample_output_path)
371
481
  output = File.read(sample_output_path)
372
482
  assert !output.empty?
@@ -376,16 +486,16 @@ text
376
486
  assert_xpath '/html/head/title[text() = "Document Title"]', output, 1
377
487
  assert_xpath '/html/body/*[@id="header"]/h1[text() = "Document Title"]', output, 1
378
488
  ensure
379
- FileUtils::rm(sample_output_path)
489
+ FileUtils.rm(sample_output_path)
380
490
  end
381
491
  end
382
492
 
383
- test 'should render document to file when base dir is set' do
493
+ test 'should convert source file and write to specified file in base_dir' do
384
494
  sample_input_path = fixture_path('sample.asciidoc')
385
495
  sample_output_path = fixture_path('result.html')
386
496
  fixture_dir = fixture_path('')
387
497
  begin
388
- Asciidoctor.render_file(sample_input_path, :to_file => 'result.html', :base_dir => fixture_dir)
498
+ Asciidoctor.convert_file sample_input_path, :to_file => 'result.html', :base_dir => fixture_dir
389
499
  assert File.exist?(sample_output_path)
390
500
  output = File.read(sample_output_path)
391
501
  assert !output.empty?
@@ -397,45 +507,43 @@ text
397
507
  rescue => e
398
508
  flunk e.message
399
509
  ensure
400
- FileUtils::rm(sample_output_path, :force => true)
510
+ FileUtils.rm(sample_output_path, :force => true)
401
511
  end
402
512
  end
403
513
 
404
- test 'in_place option must not be used with to_file option' do
514
+ test 'in_place option is ignored when to_file is specified' do
405
515
  sample_input_path = fixture_path('sample.asciidoc')
406
516
  sample_output_path = fixture_path('result.html')
407
- assert_raise ArgumentError do
408
- begin
409
- Asciidoctor.render_file(sample_input_path, :to_file => sample_output_path, :in_place => true)
410
- ensure
411
- FileUtils::rm(sample_output_path) if File.exists? sample_output_path
412
- end
517
+ begin
518
+ Asciidoctor.convert_file sample_input_path, :to_file => sample_output_path, :in_place => true
519
+ assert File.exist?(sample_output_path)
520
+ ensure
521
+ FileUtils.rm(sample_output_path) if File.exist? sample_output_path
413
522
  end
414
523
  end
415
524
 
416
- test 'in_place option must not be used with to_dir option' do
525
+ test 'in_place option is ignored when to_dir is specified' do
417
526
  sample_input_path = fixture_path('sample.asciidoc')
418
- sample_output_path = fixture_path('result.html')
419
- assert_raise ArgumentError do
420
- begin
421
- Asciidoctor.render_file(sample_input_path, :to_dir => '', :in_place => true)
422
- ensure
423
- FileUtils::rm(sample_output_path) if File.exists? sample_output_path
424
- end
527
+ sample_output_path = fixture_path('sample.html')
528
+ begin
529
+ Asciidoctor.convert_file sample_input_path, :to_dir => File.dirname(sample_output_path), :in_place => true
530
+ assert File.exist?(sample_output_path)
531
+ ensure
532
+ FileUtils.rm(sample_output_path) if File.exist? sample_output_path
425
533
  end
426
534
  end
427
535
 
428
536
  test 'output should be relative to to_dir option' do
429
537
  sample_input_path = fixture_path('sample.asciidoc')
430
538
  output_dir = File.join(File.dirname(sample_input_path), 'test_output')
431
- Dir.mkdir output_dir if !File.exists? output_dir
539
+ Dir.mkdir output_dir if !File.exist? output_dir
432
540
  sample_output_path = File.join(output_dir, 'sample.html')
433
541
  begin
434
- Asciidoctor.render_file(sample_input_path, :to_dir => output_dir)
435
- assert File.exists? sample_output_path
542
+ Asciidoctor.convert_file sample_input_path, :to_dir => output_dir
543
+ assert File.exist? sample_output_path
436
544
  ensure
437
- FileUtils::rm(sample_output_path) if File.exists? sample_output_path
438
- FileUtils::rmdir output_dir
545
+ FileUtils.rm(sample_output_path) if File.exist? sample_output_path
546
+ FileUtils.rmdir output_dir
439
547
  end
440
548
  end
441
549
 
@@ -444,12 +552,21 @@ text
444
552
  output_dir = File.join(File.join(File.dirname(sample_input_path), 'test_output'), 'subdir')
445
553
  sample_output_path = File.join(output_dir, 'sample.html')
446
554
  begin
447
- Asciidoctor.render_file(sample_input_path, :to_dir => output_dir, :mkdirs => true)
448
- assert File.exists? sample_output_path
555
+ Asciidoctor.convert_file sample_input_path, :to_dir => output_dir, :mkdirs => true
556
+ assert File.exist? sample_output_path
449
557
  ensure
450
- FileUtils::rm(sample_output_path) if File.exists? sample_output_path
451
- FileUtils::rmdir output_dir
452
- FileUtils::rmdir File.dirname(output_dir)
558
+ FileUtils.rm(sample_output_path) if File.exist? sample_output_path
559
+ FileUtils.rmdir output_dir
560
+ FileUtils.rmdir File.dirname(output_dir)
561
+ end
562
+ end
563
+
564
+ # TODO need similar test for when to_dir is specified
565
+ test 'should raise exception if an attempt is made to overwrite input file' do
566
+ sample_input_path = fixture_path('sample.asciidoc')
567
+
568
+ assert_raises IOError do
569
+ Asciidoctor.convert_file sample_input_path, :attributes => { 'outfilesuffix' => '.asciidoc' }
453
570
  end
454
571
  end
455
572
 
@@ -458,14 +575,28 @@ text
458
575
  base_dir = File.dirname(sample_input_path)
459
576
  sample_rel_output_path = File.join('test_output', 'result.html')
460
577
  output_dir = File.dirname(File.join(base_dir, sample_rel_output_path))
461
- Dir.mkdir output_dir if !File.exists? output_dir
578
+ Dir.mkdir output_dir if !File.exist? output_dir
462
579
  sample_output_path = File.join(base_dir, sample_rel_output_path)
463
580
  begin
464
- Asciidoctor.render_file(sample_input_path, :to_dir => base_dir, :to_file => sample_rel_output_path)
465
- assert File.exists? sample_output_path
581
+ Asciidoctor.convert_file sample_input_path, :to_dir => base_dir, :to_file => sample_rel_output_path
582
+ assert File.exist? sample_output_path
466
583
  ensure
467
- FileUtils::rm(sample_output_path) if File.exists? sample_output_path
468
- FileUtils::rmdir output_dir
584
+ FileUtils.rm(sample_output_path) if File.exist? sample_output_path
585
+ FileUtils.rmdir output_dir
586
+ end
587
+ end
588
+
589
+ test 'should not modify options argument' do
590
+ options = {
591
+ :safe => Asciidoctor::SafeMode::SAFE,
592
+ :to_file => false
593
+ }
594
+ options.freeze
595
+ sample_input_path = fixture_path('sample.asciidoc')
596
+ begin
597
+ Asciidoctor.convert_file sample_input_path, options
598
+ rescue
599
+ flunk %(options argument should not be modified)
469
600
  end
470
601
  end
471
602
  end
@@ -474,20 +605,20 @@ text
474
605
  test 'should include docinfo files for html backend' do
475
606
  sample_input_path = fixture_path('basic.asciidoc')
476
607
 
477
- output = Asciidoctor.render_file(sample_input_path,
478
- :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo' => ''})
608
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
609
+ :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo' => ''}
479
610
  assert !output.empty?
480
611
  assert_css 'script[src="modernizr.js"]', output, 1
481
612
  assert_css 'meta[http-equiv="imagetoolbar"]', output, 0
482
613
 
483
- output = Asciidoctor.render_file(sample_input_path,
484
- :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo1' => ''})
614
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
615
+ :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo1' => ''}
485
616
  assert !output.empty?
486
617
  assert_css 'script[src="modernizr.js"]', output, 0
487
618
  assert_css 'meta[http-equiv="imagetoolbar"]', output, 1
488
619
 
489
- output = Asciidoctor.render_file(sample_input_path,
490
- :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo2' => ''})
620
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
621
+ :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo2' => ''}
491
622
  assert !output.empty?
492
623
  assert_css 'script[src="modernizr.js"]', output, 1
493
624
  assert_css 'meta[http-equiv="imagetoolbar"]', output, 1
@@ -496,24 +627,26 @@ text
496
627
  test 'should include docinfo files for docbook backend' do
497
628
  sample_input_path = fixture_path('basic.asciidoc')
498
629
 
499
- output = Asciidoctor.render_file(sample_input_path,
500
- :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo' => ''})
630
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
631
+ :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo' => ''}
501
632
  assert !output.empty?
502
633
  assert_css 'productname', output, 0
503
634
  assert_css 'copyright', output, 1
504
635
 
505
- output = Asciidoctor.render_file(sample_input_path,
506
- :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo1' => ''})
636
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
637
+ :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo1' => ''}
507
638
  assert !output.empty?
508
639
  assert_css 'productname', output, 1
640
+ assert_xpath '//xmlns:productname[text()="Asciidoctor™"]', output, 1
509
641
  assert_css 'edition', output, 1
510
642
  assert_xpath '//xmlns:edition[text()="1.0"]', output, 1 # verifies substitutions are performed
511
643
  assert_css 'copyright', output, 0
512
644
 
513
- output = Asciidoctor.render_file(sample_input_path,
514
- :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo2' => ''})
645
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
646
+ :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo2' => ''}
515
647
  assert !output.empty?
516
648
  assert_css 'productname', output, 1
649
+ assert_xpath '//xmlns:productname[text()="Asciidoctor™"]', output, 1
517
650
  assert_css 'edition', output, 1
518
651
  assert_xpath '//xmlns:edition[text()="1.0"]', output, 1 # verifies substitutions are performed
519
652
  assert_css 'copyright', output, 1
@@ -522,20 +655,20 @@ text
522
655
  test 'should include docinfo footer files for html backend' do
523
656
  sample_input_path = fixture_path('basic.asciidoc')
524
657
 
525
- output = Asciidoctor.render_file(sample_input_path,
526
- :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo' => ''})
658
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
659
+ :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo' => ''}
527
660
  assert !output.empty?
528
661
  assert_css 'body script', output, 1
529
662
  assert_css 'a#top', output, 0
530
663
 
531
- output = Asciidoctor.render_file(sample_input_path,
532
- :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo1' => ''})
664
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
665
+ :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo1' => ''}
533
666
  assert !output.empty?
534
667
  assert_css 'body script', output, 0
535
668
  assert_css 'a#top', output, 1
536
669
 
537
- output = Asciidoctor.render_file(sample_input_path,
538
- :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo2' => ''})
670
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
671
+ :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo2' => ''}
539
672
  assert !output.empty?
540
673
  assert_css 'body script', output, 1
541
674
  assert_css 'a#top', output, 1
@@ -544,38 +677,69 @@ text
544
677
  test 'should include docinfo footer files for docbook backend' do
545
678
  sample_input_path = fixture_path('basic.asciidoc')
546
679
 
547
- output = Asciidoctor.render_file(sample_input_path,
548
- :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo' => ''})
680
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
681
+ :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo' => ''}
549
682
  assert !output.empty?
550
683
  assert_css 'article > revhistory', output, 1
551
684
  assert_xpath '/xmlns:article/xmlns:revhistory/xmlns:revision/xmlns:revnumber[text()="1.0"]', output, 1 # verifies substitutions are performed
552
685
  assert_css 'glossary#_glossary', output, 0
553
686
 
554
- output = Asciidoctor.render_file(sample_input_path,
555
- :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo1' => ''})
687
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
688
+ :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo1' => ''}
556
689
  assert !output.empty?
557
690
  assert_css 'article > revhistory', output, 0
558
691
  assert_css 'glossary#_glossary', output, 1
559
692
 
560
- output = Asciidoctor.render_file(sample_input_path,
561
- :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo2' => ''})
693
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
694
+ :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo2' => ''}
562
695
  assert !output.empty?
563
696
  assert_css 'article > revhistory', output, 1
564
697
  assert_xpath '/xmlns:article/xmlns:revhistory/xmlns:revision/xmlns:revnumber[text()="1.0"]', output, 1 # verifies substitutions are performed
565
698
  assert_css 'glossary#_glossary', output, 1
566
699
  end
567
700
 
701
+ # WARNING this test manipulates runtime settings; should probably be run in forked process
702
+ test 'should force encoding of docinfo files to UTF-8' do
703
+ sample_input_path = fixture_path('basic.asciidoc')
704
+
705
+ if RUBY_VERSION >= '1.9'
706
+ default_external_old = Encoding.default_external
707
+ force_encoding_old = Asciidoctor::FORCE_ENCODING
708
+ verbose_old = $VERBOSE
709
+ end
710
+ begin
711
+ if RUBY_VERSION >= '1.9'
712
+ $VERBOSE = nil # disable warnings since we have to modify constants
713
+ Encoding.default_external = 'US-ASCII'
714
+ Asciidoctor::FORCE_ENCODING = true
715
+ end
716
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
717
+ :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo2' => ''}
718
+ assert !output.empty?
719
+ assert_css 'productname', output, 1
720
+ assert_css 'edition', output, 1
721
+ assert_xpath '//xmlns:edition[text()="1.0"]', output, 1 # verifies substitutions are performed
722
+ assert_css 'copyright', output, 1
723
+ ensure
724
+ if RUBY_VERSION >= '1.9'
725
+ Encoding.default_external = default_external_old
726
+ Asciidoctor::FORCE_ENCODING = force_encoding_old
727
+ $VERBOSE = verbose_old
728
+ end
729
+ end
730
+ end
731
+
568
732
  test 'should not include docinfo files by default' do
569
733
  sample_input_path = fixture_path('basic.asciidoc')
570
734
 
571
- output = Asciidoctor.render_file(sample_input_path,
572
- :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER)
735
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
736
+ :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER
573
737
  assert !output.empty?
574
738
  assert_css 'script[src="modernizr.js"]', output, 0
575
739
  assert_css 'meta[http-equiv="imagetoolbar"]', output, 0
576
740
 
577
- output = Asciidoctor.render_file(sample_input_path,
578
- :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER)
741
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
742
+ :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER
579
743
  assert !output.empty?
580
744
  assert_css 'productname', output, 0
581
745
  assert_css 'copyright', output, 0
@@ -584,93 +748,67 @@ text
584
748
  test 'should not include docinfo files if safe mode is SECURE or greater' do
585
749
  sample_input_path = fixture_path('basic.asciidoc')
586
750
 
587
- output = Asciidoctor.render_file(sample_input_path,
588
- :header_footer => true, :attributes => {'docinfo2' => ''})
751
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
752
+ :header_footer => true, :attributes => {'docinfo2' => ''}
589
753
  assert !output.empty?
590
754
  assert_css 'script[src="modernizr.js"]', output, 0
591
755
  assert_css 'meta[http-equiv="imagetoolbar"]', output, 0
592
756
 
593
- output = Asciidoctor.render_file(sample_input_path,
594
- :header_footer => true, :backend => 'docbook', :attributes => {'docinfo2' => ''})
757
+ output = Asciidoctor.convert_file sample_input_path, :to_file => false,
758
+ :header_footer => true, :backend => 'docbook', :attributes => {'docinfo2' => ''}
595
759
  assert !output.empty?
596
760
  assert_css 'productname', output, 0
597
761
  assert_css 'copyright', output, 0
598
762
  end
599
763
  end
600
764
 
601
- context 'Renderer' do
765
+ context 'MathJax' do
766
+ test 'should add MathJax script to HTML head if stem attribute is set' do
767
+ output = render_string '', :attributes => {'stem' => ''}
768
+ assert_match('<script type="text/x-mathjax-config">', output)
769
+ end
770
+ end
771
+
772
+ context 'Converter' do
602
773
  test 'built-in HTML5 views are registered by default' do
603
774
  doc = document_from_string ''
604
775
  assert_equal 'html5', doc.attributes['backend']
605
776
  assert doc.attributes.has_key? 'backend-html5'
606
777
  assert_equal 'html', doc.attributes['basebackend']
607
778
  assert doc.attributes.has_key? 'basebackend-html'
608
- renderer = doc.renderer
609
- assert !renderer.nil?
610
- views = renderer.views
611
- assert !views.nil?
612
- assert_equal 36, views.size
613
- assert views.has_key? 'document'
614
- assert Asciidoctor.const_defined?(:HTML5)
615
- assert Asciidoctor::HTML5.const_defined?(:DocumentTemplate)
779
+ converter = doc.converter
780
+ assert converter.is_a? Asciidoctor::Converter::Html5Converter
781
+ BUILT_IN_ELEMENTS.each do |element|
782
+ assert converter.respond_to? element
783
+ end
616
784
  end
617
785
 
618
786
  test 'built-in DocBook45 views are registered when backend is docbook45' do
619
787
  doc = document_from_string '', :attributes => {'backend' => 'docbook45'}
620
- renderer = doc.renderer
788
+ converter = doc.converter
621
789
  assert_equal 'docbook45', doc.attributes['backend']
622
790
  assert doc.attributes.has_key? 'backend-docbook45'
623
791
  assert_equal 'docbook', doc.attributes['basebackend']
624
792
  assert doc.attributes.has_key? 'basebackend-docbook'
625
- assert !renderer.nil?
626
- views = renderer.views
627
- assert !views.nil?
628
- assert_equal 36, views.size
629
- assert views.has_key? 'document'
630
- assert Asciidoctor.const_defined?(:DocBook45)
631
- assert Asciidoctor::DocBook45.const_defined?(:DocumentTemplate)
793
+ converter = doc.converter
794
+ assert converter.is_a? Asciidoctor::Converter::DocBook45Converter
795
+ BUILT_IN_ELEMENTS.each do |element|
796
+ assert converter.respond_to? element
797
+ end
632
798
  end
633
799
 
634
800
  test 'built-in DocBook5 views are registered when backend is docbook5' do
635
801
  doc = document_from_string '', :attributes => {'backend' => 'docbook5'}
636
- renderer = doc.renderer
802
+ converter = doc.converter
637
803
  assert_equal 'docbook5', doc.attributes['backend']
638
804
  assert doc.attributes.has_key? 'backend-docbook5'
639
805
  assert_equal 'docbook', doc.attributes['basebackend']
640
806
  assert doc.attributes.has_key? 'basebackend-docbook'
641
- assert !renderer.nil?
642
- views = renderer.views
643
- assert !views.nil?
644
- assert_equal 36, views.size
645
- assert views.has_key? 'document'
646
- assert Asciidoctor.const_defined?(:DocBook5)
647
- assert Asciidoctor::DocBook5.const_defined?(:DocumentTemplate)
648
- end
649
-
650
- test 'eRuby implementation should default to ERB' do
651
- # intentionally use built-in templates for this test
652
- doc = Asciidoctor::Document.new [], :header_footer => true
653
- renderer = doc.renderer
654
- views = renderer.views
655
- assert !views.nil?
656
- assert views.has_key? 'document'
657
- assert views['document'].is_a?(Asciidoctor::HTML5::DocumentTemplate)
658
- assert_equal 'ERB', views['document'].eruby.to_s
659
- assert_equal 'ERB', views['document'].template.class.to_s
660
- end
661
-
662
- test 'can set erubis as eRuby implementation' do
663
- # intentionally use built-in templates for this test
664
- doc = Asciidoctor::Document.new [], :eruby => 'erubis', :header_footer => true
665
- assert $LOADED_FEATURES.detect {|p| p == 'erubis.rb' || p.end_with?('/erubis.rb') }.nil?
666
- renderer = doc.renderer
667
- assert $LOADED_FEATURES.detect {|p| p == 'erubis.rb' || p.end_with?('/erubis.rb') }
668
- views = renderer.views
669
- assert !views.nil?
670
- assert views.has_key? 'document'
671
- assert views['document'].is_a?(Asciidoctor::HTML5::DocumentTemplate)
672
- assert_equal 'Erubis::FastEruby', views['document'].eruby.to_s
673
- assert_equal 'Erubis::FastEruby', views['document'].template.class.to_s
807
+ converter = doc.converter
808
+ assert converter.is_a? Asciidoctor::Converter::DocBook5Converter
809
+ BUILT_IN_ELEMENTS.each do |element|
810
+ assert converter.respond_to? element
811
+ end
674
812
  end
675
813
  end
676
814
 
@@ -683,6 +821,22 @@ text
683
821
  assert_nil doc.header
684
822
  end
685
823
 
824
+ test 'document with subtitle' do
825
+ input = <<-EOS
826
+ = Main Title: *Subtitle*
827
+ Author Name
828
+
829
+ content
830
+ EOS
831
+
832
+ doc = document_from_string input
833
+ title = doc.doctitle :partition => true, :sanitize => true
834
+ assert title.subtitle?
835
+ assert title.sanitized?
836
+ assert_equal 'Main Title', title.main
837
+ assert_equal 'Subtitle', title.subtitle
838
+ end
839
+
686
840
  test 'document with doctitle defined as attribute entry' do
687
841
  input = <<-EOS
688
842
  :doctitle: Document Title
@@ -825,17 +979,71 @@ content
825
979
  = AsciiDoc
826
980
  Stuart Rackham <founder@asciidoc.org>
827
981
  v8.6.8, 2012-07-12: See changelog.
982
+ :description: AsciiDoc user guide
983
+ :keywords: asciidoc,documentation
984
+ :copyright: Stuart Rackham
828
985
 
829
986
  == Version 8.6.8
830
987
 
831
988
  more info...
832
989
  EOS
833
990
  output = render_string input
834
- assert_xpath '//*[@id="header"]/span[@id="author"][text() = "Stuart Rackham"]', output, 1
835
- assert_xpath '//*[@id="header"]/span[@id="email"]/a[@href="mailto:founder@asciidoc.org"][text() = "founder@asciidoc.org"]', output, 1
836
- assert_xpath '//*[@id="header"]/span[@id="revnumber"][text() = "version 8.6.8,"]', output, 1
837
- assert_xpath '//*[@id="header"]/span[@id="revdate"][text() = "2012-07-12"]', output, 1
838
- assert_xpath '//*[@id="header"]/span[@id="revremark"][text() = "See changelog."]', output, 1
991
+ assert_xpath '//meta[@name="author"][@content="Stuart Rackham"]', output, 1
992
+ assert_xpath '//meta[@name="description"][@content="AsciiDoc user guide"]', output, 1
993
+ assert_xpath '//meta[@name="keywords"][@content="asciidoc,documentation"]', output, 1
994
+ assert_xpath '//meta[@name="copyright"][@content="Stuart Rackham"]', output, 1
995
+ assert_xpath '//*[@id="header"]/*[@class="details"]/span[@id="author"][text() = "Stuart Rackham"]', output, 1
996
+ assert_xpath '//*[@id="header"]/*[@class="details"]/span[@id="email"]/a[@href="mailto:founder@asciidoc.org"][text() = "founder@asciidoc.org"]', output, 1
997
+ assert_xpath '//*[@id="header"]/*[@class="details"]/span[@id="revnumber"][text() = "version 8.6.8,"]', output, 1
998
+ assert_xpath '//*[@id="header"]/*[@class="details"]/span[@id="revdate"][text() = "2012-07-12"]', output, 1
999
+ assert_xpath '//*[@id="header"]/*[@class="details"]/span[@id="revremark"][text() = "See changelog."]', output, 1
1000
+ end
1001
+
1002
+ test 'should include revision history if revdate and revnumber is set' do
1003
+ input = <<-EOS
1004
+ = Document Title
1005
+ Author Name
1006
+ :revdate: 2011-11-11
1007
+ :revnumber: 1.0
1008
+
1009
+ content
1010
+ EOS
1011
+
1012
+ output = render_string input, :backend => 'docbook'
1013
+ assert_css 'revhistory', output, 1
1014
+ assert_css 'revhistory > revision', output, 1
1015
+ assert_css 'revhistory > revision > date', output, 1
1016
+ assert_css 'revhistory > revision > revnumber', output, 1
1017
+ end
1018
+
1019
+ test 'should include revision history if revdate and revremark is set' do
1020
+ input = <<-EOS
1021
+ = Document Title
1022
+ Author Name
1023
+ :revdate: 2011-11-11
1024
+ :revremark: features!
1025
+
1026
+ content
1027
+ EOS
1028
+
1029
+ output = render_string input, :backend => 'docbook'
1030
+ assert_css 'revhistory', output, 1
1031
+ assert_css 'revhistory > revision', output, 1
1032
+ assert_css 'revhistory > revision > date', output, 1
1033
+ assert_css 'revhistory > revision > revremark', output, 1
1034
+ end
1035
+
1036
+ test 'should not include revision history if revdate is not set' do
1037
+ input = <<-EOS
1038
+ = Document Title
1039
+ Author Name
1040
+ :revnumber: 1.0
1041
+
1042
+ content
1043
+ EOS
1044
+
1045
+ output = render_string input, :backend => 'docbook'
1046
+ assert_css 'revhistory', output, 0
839
1047
  end
840
1048
 
841
1049
  test 'with metadata to DocBook45' do
@@ -848,7 +1056,7 @@ v8.6.8, 2012-07-12: See changelog.
848
1056
 
849
1057
  more info...
850
1058
  EOS
851
- output = render_string input, :backend => 'docbook'
1059
+ output = render_string input, :backend => 'docbook45'
852
1060
  assert_xpath '/article/articleinfo', output, 1
853
1061
  assert_xpath '/article/articleinfo/title[text() = "AsciiDoc"]', output, 1
854
1062
  assert_xpath '/article/articleinfo/date[text() = "2012-07-12"]', output, 1
@@ -881,7 +1089,7 @@ more info...
881
1089
  assert_xpath '/article/info/author/email[text() = "founder@asciidoc.org"]', output, 1
882
1090
  end
883
1091
 
884
- test 'with author defined using attribute entry to DocBook' do
1092
+ test 'with author defined using attribute entry to DocBook 4.5' do
885
1093
  input = <<-EOS
886
1094
  = Document Title
887
1095
  :author: Doc Writer
@@ -890,7 +1098,7 @@ more info...
890
1098
  content
891
1099
  EOS
892
1100
 
893
- output = render_string input, :backend => 'docbook'
1101
+ output = render_string input, :backend => 'docbook45'
894
1102
  assert_xpath '//articleinfo/author', output, 1
895
1103
  assert_xpath '//articleinfo/author/firstname[text() = "Doc"]', output, 1
896
1104
  assert_xpath '//articleinfo/author/surname[text() = "Writer"]', output, 1
@@ -927,7 +1135,7 @@ Doc Writer <thedoctor@asciidoc.org>; Junior Writer <junior@asciidoctor.org>
927
1135
  content
928
1136
  EOS
929
1137
 
930
- output = render_string input, :backend => 'docbook'
1138
+ output = render_string input, :backend => 'docbook45'
931
1139
  assert_xpath '//articleinfo/author', output, 0
932
1140
  assert_xpath '//articleinfo/authorgroup', output, 1
933
1141
  assert_xpath '//articleinfo/authorgroup/author', output, 2
@@ -945,7 +1153,7 @@ content
945
1153
  content
946
1154
  EOS
947
1155
 
948
- output = render_string input, :backend => 'docbook'
1156
+ output = render_string input, :backend => 'docbook45'
949
1157
  assert_xpath '//articleinfo/author', output, 0
950
1158
  assert_xpath '//articleinfo/authorgroup', output, 1
951
1159
  assert_xpath '//articleinfo/authorgroup/author', output, 2
@@ -956,14 +1164,14 @@ content
956
1164
  end
957
1165
 
958
1166
  test 'with header footer' do
959
- doc = document_from_string "= Title\n\npreamble"
1167
+ doc = document_from_string "= Title\n\nparagraph"
960
1168
  assert !doc.attr?('embedded')
961
1169
  result = doc.render
962
1170
  assert_xpath '/html', result, 1
963
1171
  assert_xpath '//*[@id="header"]', result, 1
964
1172
  assert_xpath '//*[@id="header"]/h1', result, 1
965
1173
  assert_xpath '//*[@id="footer"]', result, 1
966
- assert_xpath '//*[@id="preamble"]', result, 1
1174
+ assert_xpath '//*[@id="content"]', result, 1
967
1175
  end
968
1176
 
969
1177
  test 'can disable last updated in footer' do
@@ -974,14 +1182,14 @@ content
974
1182
  end
975
1183
 
976
1184
  test 'no header footer' do
977
- doc = document_from_string "= Title\n\npreamble", :header_footer => false
1185
+ doc = document_from_string "= Document Title\n\ncontent", :header_footer => false
978
1186
  assert doc.attr?('embedded')
979
1187
  result = doc.render
980
1188
  assert_xpath '/html', result, 0
981
1189
  assert_xpath '/h1', result, 0
982
1190
  assert_xpath '/*[@id="header"]', result, 0
983
1191
  assert_xpath '/*[@id="footer"]', result, 0
984
- assert_xpath '/*[@id="preamble"]', result, 1
1192
+ assert_xpath '/*[@class="paragraph"]', result, 1
985
1193
  end
986
1194
 
987
1195
  test 'enable title in embedded document by unassigning notitle attribute' do
@@ -991,14 +1199,14 @@ content
991
1199
  content
992
1200
  EOS
993
1201
 
994
- result = render_string input, :header_footer => false, :attributes => {'notitle!' => ''}
1202
+ result = render_embedded_string input, :attributes => {'notitle!' => ''}
995
1203
  assert_xpath '/html', result, 0
996
1204
  assert_xpath '/h1', result, 1
997
1205
  assert_xpath '/*[@id="header"]', result, 0
998
1206
  assert_xpath '/*[@id="footer"]', result, 0
999
- assert_xpath '/*[@id="preamble"]', result, 1
1207
+ assert_xpath '/*[@class="paragraph"]', result, 1
1000
1208
  assert_xpath '(/*)[1]/self::h1', result, 1
1001
- assert_xpath '(/*)[2]/self::*[@id="preamble"]', result, 1
1209
+ assert_xpath '(/*)[2]/self::*[@class="paragraph"]', result, 1
1002
1210
  end
1003
1211
 
1004
1212
  test 'enable title in embedded document by assigning showtitle attribute' do
@@ -1008,14 +1216,14 @@ content
1008
1216
  content
1009
1217
  EOS
1010
1218
 
1011
- result = render_string input, :header_footer => false, :attributes => {'showtitle' => ''}
1219
+ result = render_embedded_string input, :attributes => {'showtitle' => ''}
1012
1220
  assert_xpath '/html', result, 0
1013
1221
  assert_xpath '/h1', result, 1
1014
1222
  assert_xpath '/*[@id="header"]', result, 0
1015
1223
  assert_xpath '/*[@id="footer"]', result, 0
1016
- assert_xpath '/*[@id="preamble"]', result, 1
1224
+ assert_xpath '/*[@class="paragraph"]', result, 1
1017
1225
  assert_xpath '(/*)[1]/self::h1', result, 1
1018
- assert_xpath '(/*)[2]/self::*[@id="preamble"]', result, 1
1226
+ assert_xpath '(/*)[2]/self::*[@class="paragraph"]', result, 1
1019
1227
  end
1020
1228
 
1021
1229
  test 'parse header only' do
@@ -1060,7 +1268,7 @@ finally a reference to the second footnote footnoteref:[note2].
1060
1268
  Text that has supporting information{empty}footnote:[An example footnote.].
1061
1269
  EOS
1062
1270
 
1063
- output = render_string input, :header_footer => false
1271
+ output = render_embedded_string input
1064
1272
  assert_css '#footnotes', output, 1
1065
1273
  end
1066
1274
 
@@ -1069,26 +1277,125 @@ Text that has supporting information{empty}footnote:[An example footnote.].
1069
1277
  Text that has supporting information{empty}footnote:[An example footnote.].
1070
1278
  EOS
1071
1279
 
1072
- output = render_string input, :header_footer => false, :attributes => {'nofootnotes' => ''}
1280
+ output = render_embedded_string input, :attributes => {'nofootnotes' => ''}
1073
1281
  assert_css '#footnotes', output, 0
1074
1282
  end
1075
1283
  end
1076
1284
 
1077
1285
  context 'Backends and Doctypes' do
1078
1286
  test 'html5 backend doctype article' do
1079
- result = render_string("= Title\n\npreamble", :attributes => {'backend' => 'html5'})
1287
+ result = render_string("= Title\n\nparagraph", :attributes => {'backend' => 'html5'})
1080
1288
  assert_xpath '/html', result, 1
1081
1289
  assert_xpath '/html/body[@class="article"]', result, 1
1082
1290
  assert_xpath '/html//*[@id="header"]/h1[text() = "Title"]', result, 1
1083
- assert_xpath '/html//*[@id="preamble"]//p[text() = "preamble"]', result, 1
1291
+ assert_xpath '/html//*[@id="content"]//p[text() = "paragraph"]', result, 1
1084
1292
  end
1085
1293
 
1086
1294
  test 'html5 backend doctype book' do
1087
- result = render_string("= Title\n\npreamble", :attributes => {'backend' => 'html5', 'doctype' => 'book'})
1295
+ result = render_string("= Title\n\nparagraph", :attributes => {'backend' => 'html5', 'doctype' => 'book'})
1088
1296
  assert_xpath '/html', result, 1
1089
1297
  assert_xpath '/html/body[@class="book"]', result, 1
1090
1298
  assert_xpath '/html//*[@id="header"]/h1[text() = "Title"]', result, 1
1091
- assert_xpath '/html//*[@id="preamble"]//p[text() = "preamble"]', result, 1
1299
+ assert_xpath '/html//*[@id="content"]//p[text() = "paragraph"]', result, 1
1300
+ end
1301
+
1302
+ test 'xhtml5 backend should map to html5 and set htmlsyntax to xml' do
1303
+ input = <<-EOS
1304
+ content
1305
+ EOS
1306
+ doc = document_from_string input, :backend => :xhtml5
1307
+ assert_equal 'html5', doc.backend
1308
+ assert_equal 'xml', (doc.attr 'htmlsyntax')
1309
+ end
1310
+
1311
+ test 'xhtml backend should map to html5 and set htmlsyntax to xml' do
1312
+ input = <<-EOS
1313
+ content
1314
+ EOS
1315
+ doc = document_from_string input, :backend => :xhtml
1316
+ assert_equal 'html5', doc.backend
1317
+ assert_equal 'xml', (doc.attr 'htmlsyntax')
1318
+ end
1319
+
1320
+ test 'should close all short tags when htmlsyntax is xml' do
1321
+ input = <<-EOS
1322
+ = Document Title
1323
+ Author Name
1324
+ v1.0, 2001-01-01
1325
+ :icons:
1326
+
1327
+ image:tiger.png[]
1328
+
1329
+ image::tiger.png[]
1330
+
1331
+ * [x] one
1332
+ * [ ] two
1333
+
1334
+ |===
1335
+ |A |B
1336
+ |===
1337
+
1338
+ [horizontal, labelwidth="25%", itemwidth="75%"]
1339
+ term:: definition
1340
+
1341
+ NOTE: note
1342
+
1343
+ [quote,Author,Source]
1344
+ ____
1345
+ Quote me.
1346
+ ____
1347
+
1348
+ [verse,Author,Source]
1349
+ ____
1350
+ A tall tale.
1351
+ ____
1352
+
1353
+ [options="autoplay,loop"]
1354
+ video::screencast.ogg[]
1355
+
1356
+ video::12345[vimeo]
1357
+
1358
+ [options="autoplay,loop"]
1359
+ audio::podcast.ogg[]
1360
+
1361
+ one +
1362
+ two
1363
+
1364
+ '''
1365
+ EOS
1366
+ result = render_string input, :safe => :safe, :backend => :xhtml
1367
+ begin
1368
+ Nokogiri::XML::Document.parse(result) {|config|
1369
+ config.options = Nokogiri::XML::ParseOptions::STRICT | Nokogiri::XML::ParseOptions::NONET
1370
+ }
1371
+ rescue => e
1372
+ flunk "xhtml5 backend did not generate well-formed XML: #{e.message}\n#{result}"
1373
+ end
1374
+ #refute_match(/<meta [^>]+[^\/]>/, result)
1375
+ #refute_match(/<link [^>]+[^\/]>/, result)
1376
+ #refute_match(/<img [^>]+[^\/]>/, result)
1377
+ #refute_match(/<input [^>]+[^\/]>/, result)
1378
+ #assert_match(/<input [^>]+checked="checked"/, result)
1379
+ #assert_match(/<input [^>]+disabled="disabled"/, result)
1380
+ #refute_match(/<col [^>]+[^\/]>/, result)
1381
+ #refute_match(/<[bh]r>/, result)
1382
+ #assert_match(/video [^>]+loop="loop"/, result)
1383
+ #assert_match(/video [^>]+autoplay="autoplay"/, result)
1384
+ #assert_match(/video [^>]+controls="controls"/, result)
1385
+ #assert_match(/audio [^>]+loop="loop"/, result)
1386
+ #assert_match(/audio [^>]+autoplay="autoplay"/, result)
1387
+ #assert_match(/audio [^>]+controls="controls"/, result)
1388
+ #assert_match(/iframe [^>]+webkitallowfullscreen="webkitallowfullscreen"/i, result)
1389
+ #assert_match(/iframe [^>]+mozallowfullscreen="mozallowfullscreen"/i, result)
1390
+ #assert_match(/iframe [^>]+allowfullscreen="allowfullscreen"/i, result)
1391
+ end
1392
+
1393
+ test 'xhtml backend should emit elements in proper namespace' do
1394
+ input = <<-EOS
1395
+ content
1396
+ EOS
1397
+ result = render_string input, :safe => :safe, :backend => :xhtml, :keep_namespaces => true
1398
+ assert_xpath '//*[not(namespace-uri() = "http://www.w3.org/1999/xhtml")]', result, 0
1092
1399
  end
1093
1400
 
1094
1401
  test 'docbook45 backend doctype article' do
@@ -1118,8 +1425,8 @@ section body
1118
1425
  end
1119
1426
 
1120
1427
  test 'docbook45 backend doctype article no xmlns' do
1121
- result = render_string('text', :keep_namespaces => true, :attributes => {'backend' => 'docbook45', 'doctype' => 'article', 'noxmlns' => ''})
1122
- assert_no_match(RE_XMLNS_ATTRIBUTE, result)
1428
+ result = render_string('text', :keep_namespaces => true, :attributes => {'backend' => 'docbook45', 'doctype' => 'article'})
1429
+ refute_match(RE_XMLNS_ATTRIBUTE, result)
1123
1430
  end
1124
1431
 
1125
1432
  test 'docbook45 backend doctype book' do
@@ -1145,12 +1452,13 @@ chapter body
1145
1452
  result = render_string('text', :attributes => {'backend' => 'docbook45', 'doctype' => 'book'})
1146
1453
  assert_xpath '/book', result, 1
1147
1454
  assert_xpath '/book/bookinfo/date', result, 1
1148
- assert_xpath '/book/simpara[text() = "text"]', result, 1
1455
+ # NOTE simpara cannot be a direct child of book, so content must be treated as a preface
1456
+ assert_xpath '/book/preface/simpara[text() = "text"]', result, 1
1149
1457
  end
1150
1458
 
1151
1459
  test 'docbook45 backend doctype book no xmlns' do
1152
- result = render_string('text', :keep_namespaces => true, :attributes => {'backend' => 'docbook45', 'doctype' => 'book', 'noxmlns' => ''})
1153
- assert_no_match(RE_XMLNS_ATTRIBUTE, result)
1460
+ result = render_string('text', :keep_namespaces => true, :attributes => {'backend' => 'docbook45', 'doctype' => 'book'})
1461
+ refute_match(RE_XMLNS_ATTRIBUTE, result)
1154
1462
  end
1155
1463
 
1156
1464
  test 'docbook45 backend parses out subtitle' do
@@ -1189,8 +1497,8 @@ section body
1189
1497
  section = xmlnodes_at_xpath('/xmlns:article/xmlns:section', result, 1).first
1190
1498
  # nokogiri can't make up its mind
1191
1499
  id_attr = section.attribute('id') || section.attribute('xml:id')
1192
- assert_not_nil id_attr
1193
- assert_not_nil id_attr.namespace
1500
+ refute_nil id_attr
1501
+ refute_nil id_attr.namespace
1194
1502
  assert_equal 'xml', id_attr.namespace.prefix
1195
1503
  assert_equal '_first_section', id_attr.value
1196
1504
  end
@@ -1218,29 +1526,29 @@ chapter body
1218
1526
  chapter = xmlnodes_at_xpath('/xmlns:book/xmlns:chapter', result, 1).first
1219
1527
  # nokogiri can't make up its mind
1220
1528
  id_attr = chapter.attribute('id') || chapter.attribute('xml:id')
1221
- assert_not_nil id_attr
1222
- assert_not_nil id_attr.namespace
1529
+ refute_nil id_attr
1530
+ refute_nil id_attr.namespace
1223
1531
  assert_equal 'xml', id_attr.namespace.prefix
1224
1532
  assert_equal '_first_chapter', id_attr.value
1225
1533
  end
1226
1534
 
1227
1535
  test 'should be able to set backend using :backend option key' do
1228
- doc = Asciidoctor::Document.new([], :backend => 'html5')
1536
+ doc = empty_document :backend => 'html5'
1229
1537
  assert_equal 'html5', doc.attributes['backend']
1230
1538
  end
1231
1539
 
1232
1540
  test ':backend option should override backend attribute' do
1233
- doc = Asciidoctor::Document.new([], :backend => 'html5', :attributes => {'backend' => 'docbook45'})
1541
+ doc = empty_document :backend => 'html5', :attributes => {'backend' => 'docbook45'}
1234
1542
  assert_equal 'html5', doc.attributes['backend']
1235
1543
  end
1236
1544
 
1237
1545
  test 'should be able to set doctype using :doctype option key' do
1238
- doc = Asciidoctor::Document.new([], :doctype => 'book')
1546
+ doc = empty_document :doctype => 'book'
1239
1547
  assert_equal 'book', doc.attributes['doctype']
1240
1548
  end
1241
1549
 
1242
1550
  test ':doctype option should override doctype attribute' do
1243
- doc = Asciidoctor::Document.new([], :doctype => 'book', :attributes => {'doctype' => 'article'})
1551
+ doc = empty_document :doctype => 'book', :attributes => {'doctype' => 'article'}
1244
1552
  assert_equal 'book', doc.attributes['doctype']
1245
1553
  end
1246
1554
 
@@ -1361,7 +1669,7 @@ asciidoctor - converts AsciiDoc source files to HTML, DocBook and other formats
1361
1669
 
1362
1670
  doc = document_from_string input
1363
1671
  synopsis_section = doc.blocks.first
1364
- assert_not_nil synopsis_section
1672
+ refute_nil synopsis_section
1365
1673
  assert_equal :section, synopsis_section.context
1366
1674
  assert synopsis_section.special
1367
1675
  assert_equal 'synopsis', synopsis_section.sectname
@@ -1393,14 +1701,14 @@ asciidoctor - converts AsciiDoc source files to HTML, DocBook and other formats
1393
1701
 
1394
1702
  context 'Secure Asset Path' do
1395
1703
  test 'allows us to specify a path relative to the current dir' do
1396
- doc = Asciidoctor::Document.new
1704
+ doc = empty_document
1397
1705
  legit_path = Dir.pwd + '/foo'
1398
1706
  assert_equal legit_path, doc.normalize_asset_path(legit_path)
1399
1707
  end
1400
1708
 
1401
1709
  test 'keeps naughty absolute paths from getting outside' do
1402
1710
  naughty_path = "#{disk_root}etc/passwd"
1403
- doc = Asciidoctor::Document.new
1711
+ doc = empty_document
1404
1712
  secure_path = doc.normalize_asset_path(naughty_path)
1405
1713
  assert naughty_path != secure_path
1406
1714
  assert_match(/^#{doc.base_dir}/, secure_path)
@@ -1408,10 +1716,21 @@ asciidoctor - converts AsciiDoc source files to HTML, DocBook and other formats
1408
1716
 
1409
1717
  test 'keeps naughty relative paths from getting outside' do
1410
1718
  naughty_path = 'safe/ok/../../../../../etc/passwd'
1411
- doc = Asciidoctor::Document.new
1719
+ doc = empty_document
1412
1720
  secure_path = doc.normalize_asset_path(naughty_path)
1413
1721
  assert naughty_path != secure_path
1414
1722
  assert_match(/^#{doc.base_dir}/, secure_path)
1415
1723
  end
1724
+
1725
+ test 'should raise an exception when a converter cannot be resolved' do
1726
+ input = <<-EOS
1727
+ = Document Title
1728
+ text
1729
+ EOS
1730
+ exception = assert_raises RuntimeError do
1731
+ Asciidoctor.render(input, :backend => "unknownBackend")
1732
+ end
1733
+ assert_match(/missing converter for backend 'unknownBackend'/, exception.message)
1734
+ end
1416
1735
  end
1417
1736
  end