asciidoctor 1.5.6.2 → 1.5.7

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

Potentially problematic release.


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

Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +330 -143
  3. data/README-fr.adoc +441 -0
  4. data/README-jp.adoc +418 -0
  5. data/README-zh_CN.adoc +430 -0
  6. data/README.adoc +454 -0
  7. data/Rakefile +57 -0
  8. data/asciidoctor.gemspec +7 -1
  9. data/data/locale/attributes-ar.adoc +22 -0
  10. data/data/locale/attributes-bg.adoc +22 -0
  11. data/data/locale/attributes-ca.adoc +22 -0
  12. data/data/locale/attributes-cs.adoc +22 -0
  13. data/data/locale/attributes-da.adoc +22 -0
  14. data/data/locale/attributes-de.adoc +22 -0
  15. data/data/locale/attributes-en.adoc +23 -0
  16. data/data/locale/attributes-es.adoc +22 -0
  17. data/data/locale/attributes-fa.adoc +22 -0
  18. data/data/locale/attributes-fi.adoc +22 -0
  19. data/data/locale/attributes-fr.adoc +22 -0
  20. data/data/locale/attributes-hu.adoc +22 -0
  21. data/data/locale/attributes-id.adoc +22 -0
  22. data/data/locale/attributes-it.adoc +22 -0
  23. data/data/locale/attributes-ja.adoc +22 -0
  24. data/data/locale/attributes-kr.adoc +22 -0
  25. data/data/locale/attributes-nb.adoc +22 -0
  26. data/data/locale/attributes-nl.adoc +22 -0
  27. data/data/locale/attributes-nn.adoc +22 -0
  28. data/data/locale/attributes-pl.adoc +22 -0
  29. data/data/locale/attributes-pt.adoc +22 -0
  30. data/data/locale/attributes-pt_BR.adoc +22 -0
  31. data/data/locale/attributes-ro.adoc +22 -0
  32. data/data/locale/attributes-ru.adoc +22 -0
  33. data/data/locale/attributes-sr.adoc +22 -0
  34. data/data/locale/attributes-sr_Latn.adoc +22 -0
  35. data/data/locale/attributes-tr.adoc +22 -0
  36. data/data/locale/attributes-uk.adoc +22 -0
  37. data/data/locale/attributes-zh_CN.adoc +22 -0
  38. data/data/locale/attributes-zh_TW.adoc +22 -0
  39. data/data/locale/attributes.adoc +8 -649
  40. data/data/stylesheets/asciidoctor-default.css +77 -72
  41. data/features/xref.feature +366 -7
  42. data/lib/asciidoctor.rb +107 -93
  43. data/lib/asciidoctor/abstract_block.rb +247 -239
  44. data/lib/asciidoctor/abstract_node.rb +56 -58
  45. data/lib/asciidoctor/block.rb +3 -3
  46. data/lib/asciidoctor/callouts.rb +1 -1
  47. data/lib/asciidoctor/cli/invoker.rb +36 -9
  48. data/lib/asciidoctor/cli/options.rb +63 -25
  49. data/lib/asciidoctor/converter.rb +23 -13
  50. data/lib/asciidoctor/converter/base.rb +4 -0
  51. data/lib/asciidoctor/converter/docbook45.rb +16 -9
  52. data/lib/asciidoctor/converter/docbook5.rb +115 -97
  53. data/lib/asciidoctor/converter/factory.rb +29 -31
  54. data/lib/asciidoctor/converter/html5.rb +229 -192
  55. data/lib/asciidoctor/converter/manpage.rb +72 -50
  56. data/lib/asciidoctor/converter/template.rb +12 -12
  57. data/lib/asciidoctor/core_ext.rb +5 -1
  58. data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +6 -0
  59. data/lib/asciidoctor/document.rb +168 -77
  60. data/lib/asciidoctor/extensions.rb +79 -47
  61. data/lib/asciidoctor/helpers.rb +33 -11
  62. data/lib/asciidoctor/inline.rb +3 -2
  63. data/lib/asciidoctor/list.rb +2 -1
  64. data/lib/asciidoctor/logging.rb +122 -0
  65. data/lib/asciidoctor/parser.rb +406 -382
  66. data/lib/asciidoctor/path_resolver.rb +169 -162
  67. data/lib/asciidoctor/reader.rb +166 -121
  68. data/lib/asciidoctor/section.rb +45 -28
  69. data/lib/asciidoctor/stylesheets.rb +13 -5
  70. data/lib/asciidoctor/substitutors.rb +328 -254
  71. data/lib/asciidoctor/table.rb +105 -48
  72. data/lib/asciidoctor/timings.rb +34 -6
  73. data/lib/asciidoctor/version.rb +1 -1
  74. data/man/asciidoctor.1 +41 -23
  75. data/man/asciidoctor.adoc +14 -8
  76. data/test/api_test.rb +1004 -0
  77. data/test/attributes_test.rb +241 -50
  78. data/test/blocks_test.rb +549 -124
  79. data/test/converter_test.rb +170 -78
  80. data/test/document_test.rb +208 -767
  81. data/test/extensions_test.rb +188 -53
  82. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +1 -1
  83. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +1 -1
  84. data/test/fixtures/file-with-missing-include.adoc +1 -0
  85. data/test/fixtures/include-file.jsx +8 -0
  86. data/test/fixtures/lists.adoc +96 -0
  87. data/test/fixtures/other-chapters.adoc +11 -0
  88. data/test/fixtures/outer-include.adoc +5 -0
  89. data/test/fixtures/sample.asciidoc +5 -1
  90. data/test/fixtures/subdir/index.adoc +3 -0
  91. data/test/fixtures/subdir/inner-include.adoc +3 -0
  92. data/test/fixtures/subdir/middle-include.adoc +5 -0
  93. data/test/fixtures/tagged-class-enclosed.rb +0 -1
  94. data/test/fixtures/unclosed-tag.adoc +3 -0
  95. data/test/fixtures/unexpected-end-tag.adoc +4 -0
  96. data/test/invoker_test.rb +101 -40
  97. data/test/links_test.rb +266 -72
  98. data/test/lists_test.rb +243 -45
  99. data/test/logger_test.rb +211 -0
  100. data/test/manpage_test.rb +124 -6
  101. data/test/options_test.rb +46 -1
  102. data/test/paragraphs_test.rb +23 -10
  103. data/test/parser_test.rb +30 -1
  104. data/test/paths_test.rb +115 -33
  105. data/test/preamble_test.rb +1 -1
  106. data/test/reader_test.rb +337 -81
  107. data/test/sections_test.rb +656 -72
  108. data/test/substitutions_test.rb +182 -57
  109. data/test/tables_test.rb +324 -57
  110. data/test/test_helper.rb +77 -32
  111. data/test/text_test.rb +7 -7
  112. metadata +67 -3
@@ -2,7 +2,7 @@
2
2
  Dan Allen; Sarah White; Ryan Waldron
3
3
  :doctype: manpage
4
4
  :man manual: Asciidoctor Manual
5
- :man source: Asciidoctor 1.5.6.2
5
+ :man source: Asciidoctor 1.5.7
6
6
  :page-layout: base
7
7
 
8
8
  == NAME
@@ -65,11 +65,7 @@ This option may be specified more than once.
65
65
  The _inline_ document type allows the content of a single paragraph to be formatted and returned without wrapping it in a containing element.
66
66
  Defaults to _article_.
67
67
 
68
- === Rendering Control
69
-
70
- *-C, --compact*::
71
- Compact the output by removing blank lines.
72
- (No longer in use).
68
+ === Document Conversion
73
69
 
74
70
  *-D, --destination-dir*=_DIR_::
75
71
  Destination output directory.
@@ -93,7 +89,7 @@ This option may be specified more than once.
93
89
 
94
90
  *-n, --section-numbers*::
95
91
  Auto-number section titles.
96
- Synonym for *--attribute numbered*.
92
+ Synonym for *--attribute sectnums*.
97
93
 
98
94
  *-o, --out-file*=_OUT_FILE_::
99
95
  Write output to file _OUT_FILE_.
@@ -102,6 +98,12 @@ This option may be specified more than once.
102
98
  If the input is read from standard input or a named pipe (fifo), then the output file defaults to stdout.
103
99
  If _OUT_FILE_ is _-_, then the output file is written to standard output.
104
100
 
101
+ *-R, --source-dir*=_DIR_::
102
+ Source directory.
103
+ Currently only used if the destination directory is also specified.
104
+ Used to preserve the directory structure of files converted within this directory in the destination directory.
105
+ If specified, the directory is resolved relative to the working directory.
106
+
105
107
  *-r, --require*=_LIBRARY_::
106
108
  Require the specified library before executing the processor, using the standard Ruby require.
107
109
  This option may be specified more than once.
@@ -121,6 +123,10 @@ Matching templates found in subsequent directories override ones previously disc
121
123
 
122
124
  === Processing Information
123
125
 
126
+ *--failure-level*=_LEVEL_::
127
+ The minimum logging level that triggers a non-zero exit code (failure).
128
+ If this option is not set (default: FATAL), the program exits with a status code zero even if warnings or errors have been logged.
129
+
124
130
  *-q, --quiet*::
125
131
  Silence warnings.
126
132
 
@@ -172,7 +178,7 @@ Refer to the *Asciidoctor* issue tracker at https://github.com/asciidoctor/ascii
172
178
 
173
179
  == RESOURCES
174
180
 
175
- *Project web site:* http://asciidoctor.org
181
+ *Project web site:* https://asciidoctor.org
176
182
 
177
183
  *Git source repository on GitHub:* https://github.com/asciidoctor/asciidoctor
178
184
 
@@ -0,0 +1,1004 @@
1
+ # encoding: UTF-8
2
+ unless defined? ASCIIDOCTOR_PROJECT_DIR
3
+ $: << File.dirname(__FILE__); $:.uniq!
4
+ require 'test_helper'
5
+ end
6
+
7
+ context 'API' do
8
+ context 'Load' do
9
+ test 'should load input file' do
10
+ sample_input_path = fixture_path('sample.asciidoc')
11
+ doc = File.open(sample_input_path) {|file| Asciidoctor.load file, :safe => Asciidoctor::SafeMode::SAFE }
12
+ assert_equal 'Document Title', doc.doctitle
13
+ assert_equal File.expand_path(sample_input_path), doc.attr('docfile')
14
+ assert_equal File.expand_path(File.dirname(sample_input_path)), doc.attr('docdir')
15
+ assert_equal '.asciidoc', doc.attr('docfilesuffix')
16
+ end
17
+
18
+ test 'should load input file from filename' do
19
+ sample_input_path = fixture_path('sample.asciidoc')
20
+ doc = Asciidoctor.load_file(sample_input_path, :safe => Asciidoctor::SafeMode::SAFE)
21
+ assert_equal 'Document Title', doc.doctitle
22
+ assert_equal File.expand_path(sample_input_path), doc.attr('docfile')
23
+ assert_equal File.expand_path(File.dirname(sample_input_path)), doc.attr('docdir')
24
+ assert_equal '.asciidoc', doc.attr('docfilesuffix')
25
+ end
26
+
27
+ test 'should not load invalid file' do
28
+ sample_input_path = fixture_path('hello-asciidoctor.pdf')
29
+ exception = assert_raises ArgumentError do
30
+ Asciidoctor.load_file(sample_input_path, :safe => Asciidoctor::SafeMode::SAFE)
31
+ end
32
+ assert_match(/Failed to load AsciiDoc document/, exception.message)
33
+ # verify we have the correct backtrace (should be in at least first 5 lines)
34
+ assert_match((RUBY_ENGINE == 'rbx' ? /parser\.rb/ : /helpers\.rb/), exception.backtrace[0..4].join("\n"))
35
+ end if RUBY_MIN_VERSION_1_9
36
+
37
+ test 'should load input IO' do
38
+ input = StringIO.new(<<-EOS)
39
+ Document Title
40
+ ==============
41
+
42
+ preamble
43
+ EOS
44
+ doc = Asciidoctor.load(input, :safe => Asciidoctor::SafeMode::SAFE)
45
+ assert_equal 'Document Title', doc.doctitle
46
+ refute doc.attr?('docfile')
47
+ assert_equal doc.base_dir, doc.attr('docdir')
48
+ end
49
+
50
+ test 'should load input string' do
51
+ input = <<-EOS
52
+ Document Title
53
+ ==============
54
+
55
+ preamble
56
+ EOS
57
+ doc = Asciidoctor.load(input, :safe => Asciidoctor::SafeMode::SAFE)
58
+ assert_equal 'Document Title', doc.doctitle
59
+ refute doc.attr?('docfile')
60
+ assert_equal doc.base_dir, doc.attr('docdir')
61
+ end
62
+
63
+ test 'should load input string array' do
64
+ input = <<-EOS
65
+ Document Title
66
+ ==============
67
+
68
+ preamble
69
+ EOS
70
+ doc = Asciidoctor.load(input.lines.entries, :safe => Asciidoctor::SafeMode::SAFE)
71
+ assert_equal 'Document Title', doc.doctitle
72
+ refute doc.attr?('docfile')
73
+ assert_equal doc.base_dir, doc.attr('docdir')
74
+ end
75
+
76
+ test 'should accept attributes as array' do
77
+ # NOTE there's a tab character before idseparator
78
+ doc = Asciidoctor.load('text', :attributes => %w(toc sectnums source-highlighter=coderay idprefix idseparator=-))
79
+ assert_kind_of Hash, doc.attributes
80
+ assert doc.attr?('toc')
81
+ assert_equal '', doc.attr('toc')
82
+ assert doc.attr?('sectnums')
83
+ assert_equal '', doc.attr('sectnums')
84
+ assert doc.attr?('source-highlighter')
85
+ assert_equal 'coderay', doc.attr('source-highlighter')
86
+ assert doc.attr?('idprefix')
87
+ assert_equal '', doc.attr('idprefix')
88
+ assert doc.attr?('idseparator')
89
+ assert_equal '-', doc.attr('idseparator')
90
+ end
91
+
92
+ test 'should accept attributes as empty array' do
93
+ doc = Asciidoctor.load('text', :attributes => [])
94
+ assert_kind_of Hash, doc.attributes
95
+ end
96
+
97
+ test 'should accept attributes as string' do
98
+ doc = Asciidoctor.load('text', :attributes => 'toc sectnums
99
+ source-highlighter=coderay
100
+ idprefix
101
+ idseparator=-')
102
+ assert_kind_of Hash, doc.attributes
103
+ assert doc.attr?('toc')
104
+ assert_equal '', doc.attr('toc')
105
+ assert doc.attr?('sectnums')
106
+ assert_equal '', doc.attr('sectnums')
107
+ assert doc.attr?('source-highlighter')
108
+ assert_equal 'coderay', doc.attr('source-highlighter')
109
+ assert doc.attr?('idprefix')
110
+ assert_equal '', doc.attr('idprefix')
111
+ assert doc.attr?('idseparator')
112
+ assert_equal '-', doc.attr('idseparator')
113
+ end
114
+
115
+ test 'should accept values containing spaces in attributes string' do
116
+ doc = Asciidoctor.load('text', :attributes => %(idprefix idseparator=- note-caption=Note\\ to\\\tself toc))
117
+ assert_kind_of Hash, doc.attributes
118
+ assert doc.attr?('idprefix')
119
+ assert_equal '', doc.attr('idprefix')
120
+ assert doc.attr?('idseparator')
121
+ assert_equal '-', doc.attr('idseparator')
122
+ assert doc.attr?('note-caption')
123
+ assert_equal "Note to\tself", doc.attr('note-caption')
124
+ end
125
+
126
+ test 'should accept attributes as empty string' do
127
+ doc = Asciidoctor.load('text', :attributes => '')
128
+ assert_kind_of Hash, doc.attributes
129
+ end
130
+
131
+ test 'should accept attributes as nil' do
132
+ doc = Asciidoctor.load('text', :attributes => nil)
133
+ assert_kind_of Hash, doc.attributes
134
+ end
135
+
136
+ test 'should accept attributes if hash like' do
137
+ class Hashish
138
+ def initialize
139
+ @table = {'toc' => ''}
140
+ end
141
+
142
+ def keys
143
+ @table.keys
144
+ end
145
+
146
+ def [](key)
147
+ @table[key]
148
+ end
149
+ end
150
+
151
+ doc = Asciidoctor.load('text', :attributes => Hashish.new)
152
+ assert_kind_of Hash, doc.attributes
153
+ assert doc.attributes.has_key?('toc')
154
+ end
155
+
156
+ test 'should not expand value of docdir attribute if specified via API' do
157
+ docdir = 'virtual/directory'
158
+ doc = document_from_string '', :safe => :safe, :attributes => { 'docdir' => docdir }
159
+ assert_equal docdir, (doc.attr 'docdir')
160
+ assert_equal docdir, doc.base_dir
161
+ end
162
+
163
+ test 'converts block to output format when convert is called' do
164
+ doc = Asciidoctor.load 'paragraph text'
165
+ expected = <<-EOS
166
+ <div class="paragraph">
167
+ <p>paragraph text</p>
168
+ </div>
169
+ EOS
170
+ assert_equal 1, doc.blocks.length
171
+ assert_equal :paragraph, doc.blocks[0].context
172
+ assert_equal expected.chomp, doc.blocks[0].convert
173
+ end
174
+
175
+ test 'render method on node is aliased to convert method' do
176
+ input = <<-EOS
177
+ paragraph text
178
+
179
+ * list item
180
+ EOS
181
+ doc = Asciidoctor.load input
182
+ assert_equal 2, doc.blocks.length
183
+ ([doc] + doc.blocks).each do |block|
184
+ assert_equal block.method(:convert), block.method(:render)
185
+ end
186
+ inline = Asciidoctor::Inline.new doc.blocks[0], :image, nil, :type => 'image', :target => 'tiger.png'
187
+ assert_equal inline.method(:convert), inline.method(:render)
188
+ end
189
+
190
+ test 'should output timestamps by default' do
191
+ doc = document_from_string 'text', :backend => :html5, :attributes => nil
192
+ result = doc.convert
193
+ assert doc.attr?('docdate')
194
+ refute doc.attr? 'reproducible'
195
+ assert_xpath '//div[@id="footer-text" and contains(string(.//text()), "Last updated")]', result, 1
196
+ end
197
+
198
+ test 'should not output timestamps if reproducible attribute is set in HTML 5' do
199
+ doc = document_from_string 'text', :backend => :html5, :attributes => { 'reproducible' => '' }
200
+ result = doc.convert
201
+ assert doc.attr?('docdate')
202
+ assert doc.attr?('reproducible')
203
+ assert_xpath '//div[@id="footer-text" and contains(string(.//text()), "Last updated")]', result, 0
204
+ end
205
+
206
+ test 'should not output timestamps if reproducible attribute is set in DocBook' do
207
+ doc = document_from_string 'text', :backend => :docbook, :attributes => { 'reproducible' => '' }
208
+ result = doc.convert
209
+ assert doc.attr?('docdate')
210
+ assert doc.attr?('reproducible')
211
+ assert_xpath '/article/info/date', result, 0
212
+ end
213
+
214
+ test 'should not modify options argument' do
215
+ options = {
216
+ :safe => Asciidoctor::SafeMode::SAFE
217
+ }
218
+ options.freeze
219
+ sample_input_path = fixture_path('sample.asciidoc')
220
+ begin
221
+ Asciidoctor.load_file sample_input_path, options
222
+ rescue
223
+ flunk %(options argument should not be modified)
224
+ end
225
+ end
226
+
227
+ test 'should not modify attributes Hash argument' do
228
+ attributes = {}
229
+ attributes.freeze
230
+ options = {
231
+ :safe => Asciidoctor::SafeMode::SAFE,
232
+ :attributes => attributes
233
+ }
234
+ sample_input_path = fixture_path('sample.asciidoc')
235
+ begin
236
+ Asciidoctor.load_file sample_input_path, options
237
+ rescue
238
+ flunk %(attributes argument should not be modified)
239
+ end
240
+ end
241
+
242
+ test 'should be able to restore header attributes after call to convert' do
243
+ input = <<-EOS
244
+ = Document Title
245
+ :foo: bar
246
+
247
+ content
248
+
249
+ :foo: baz
250
+
251
+ content
252
+ EOS
253
+ doc = Asciidoctor.load input
254
+ assert_equal 'bar', (doc.attr 'foo')
255
+ doc.convert
256
+ assert_equal 'baz', (doc.attr 'foo')
257
+ doc.restore_attributes
258
+ assert_equal 'bar', (doc.attr 'foo')
259
+ end
260
+
261
+ test 'should track file and line information with blocks if sourcemap option is set' do
262
+ doc = Asciidoctor.load_file fixture_path('sample.asciidoc'), :sourcemap => true
263
+
264
+ refute_nil doc.source_location
265
+ assert_equal 'sample.asciidoc', doc.file
266
+ assert_equal 1, doc.lineno
267
+
268
+ section_1 = doc.sections[0]
269
+ assert_equal 'Section A', section_1.title
270
+ refute_nil section_1.source_location
271
+ assert_equal 'sample.asciidoc', section_1.file
272
+ assert_equal 10, section_1.lineno
273
+
274
+ section_2 = doc.sections[1]
275
+ assert_equal 'Section B', section_2.title
276
+ refute_nil section_2.source_location
277
+ assert_equal 'sample.asciidoc', section_2.file
278
+ assert_equal 18, section_2.lineno
279
+
280
+ table_block = section_2.blocks[1]
281
+ assert_equal :table, table_block.context
282
+ refute_nil table_block.source_location
283
+ assert_equal 'sample.asciidoc', table_block.file
284
+ assert_equal 22, table_block.lineno
285
+ first_cell = table_block.rows.body[0][0]
286
+ refute_nil first_cell.source_location
287
+ assert_equal 'sample.asciidoc', first_cell.file
288
+ assert_equal 23, first_cell.lineno
289
+ second_cell = table_block.rows.body[0][1]
290
+ refute_nil second_cell.source_location
291
+ assert_equal 'sample.asciidoc', second_cell.file
292
+ assert_equal 23, second_cell.lineno
293
+ last_cell = table_block.rows.body[-1][-1]
294
+ refute_nil last_cell.source_location
295
+ assert_equal 'sample.asciidoc', last_cell.file
296
+ assert_equal 24, last_cell.lineno
297
+
298
+ last_block = section_2.blocks[-1]
299
+ assert_equal :ulist, last_block.context
300
+ refute_nil last_block.source_location
301
+ assert_equal 'sample.asciidoc', last_block.file
302
+ assert_equal 28, last_block.lineno
303
+
304
+ list_items = last_block.blocks
305
+ refute_nil list_items[0].source_location
306
+ assert_equal 'sample.asciidoc', list_items[0].file
307
+ assert_equal 28, list_items[0].lineno
308
+
309
+ refute_nil list_items[1].source_location
310
+ assert_equal 'sample.asciidoc', list_items[1].file
311
+ assert_equal 29, list_items[1].lineno
312
+
313
+ refute_nil list_items[2].source_location
314
+ assert_equal 'sample.asciidoc', list_items[2].file
315
+ assert_equal 30, list_items[2].lineno
316
+
317
+ doc = Asciidoctor.load_file fixture_path('master.adoc'), :sourcemap => true, :safe => :safe
318
+
319
+ section_1 = doc.sections[0]
320
+ assert_equal 'Chapter A', section_1.title
321
+ refute_nil section_1.source_location
322
+ assert_equal fixture_path('chapter-a.adoc'), section_1.file
323
+ assert_equal 1, section_1.lineno
324
+ end
325
+
326
+ test 'should track file and line information on list items if sourcemap option is set' do
327
+ doc = Asciidoctor.load_file fixture_path('lists.adoc'), :sourcemap => true
328
+
329
+ first_section = doc.blocks[1]
330
+
331
+ unordered_basic_list = first_section.blocks[0]
332
+ assert_equal 11, unordered_basic_list.lineno
333
+
334
+ unordered_basic_list_items = unordered_basic_list.find_by :context => :list_item
335
+ assert_equal 11, unordered_basic_list_items[0].lineno
336
+ assert_equal 12, unordered_basic_list_items[1].lineno
337
+ assert_equal 13, unordered_basic_list_items[2].lineno
338
+
339
+ unordered_max_nesting = first_section.blocks[1]
340
+ assert_equal 16, unordered_max_nesting.lineno
341
+ unordered_max_nesting_items = unordered_max_nesting.find_by :context => :list_item
342
+ assert_equal 16, unordered_max_nesting_items[0].lineno
343
+ assert_equal 17, unordered_max_nesting_items[1].lineno
344
+ assert_equal 18, unordered_max_nesting_items[2].lineno
345
+ assert_equal 19, unordered_max_nesting_items[3].lineno
346
+ assert_equal 20, unordered_max_nesting_items[4].lineno
347
+ assert_equal 21, unordered_max_nesting_items[5].lineno
348
+
349
+ checklist = first_section.blocks[2]
350
+ assert_equal 24, checklist.lineno
351
+ checklist_list_items = checklist.find_by :context => :list_item
352
+ assert_equal 24, checklist_list_items[0].lineno
353
+ assert_equal 25, checklist_list_items[1].lineno
354
+ assert_equal 26, checklist_list_items[2].lineno
355
+ assert_equal 27, checklist_list_items[3].lineno
356
+
357
+ ordered_basic = first_section.blocks[3]
358
+ assert_equal 30, ordered_basic.lineno
359
+ ordered_basic_list_items = ordered_basic.find_by :context => :list_item
360
+ assert_equal 30, ordered_basic_list_items[0].lineno
361
+ assert_equal 31, ordered_basic_list_items[1].lineno
362
+ assert_equal 32, ordered_basic_list_items[2].lineno
363
+
364
+ ordered_nested = first_section.blocks[4]
365
+ assert_equal 35, ordered_nested.lineno
366
+ ordered_nested_list_items = ordered_nested.find_by :context => :list_item
367
+ assert_equal 35, ordered_nested_list_items[0].lineno
368
+ assert_equal 36, ordered_nested_list_items[1].lineno
369
+ assert_equal 37, ordered_nested_list_items[2].lineno
370
+ assert_equal 38, ordered_nested_list_items[3].lineno
371
+ assert_equal 39, ordered_nested_list_items[4].lineno
372
+
373
+ ordered_max_nesting = first_section.blocks[5]
374
+ assert_equal 42, ordered_max_nesting.lineno
375
+ ordered_max_nesting_items = ordered_max_nesting.find_by :context => :list_item
376
+ assert_equal 42, ordered_max_nesting_items[0].lineno
377
+ assert_equal 43, ordered_max_nesting_items[1].lineno
378
+ assert_equal 44, ordered_max_nesting_items[2].lineno
379
+ assert_equal 45, ordered_max_nesting_items[3].lineno
380
+ assert_equal 46, ordered_max_nesting_items[4].lineno
381
+ assert_equal 47, ordered_max_nesting_items[5].lineno
382
+
383
+ labeled_singleline = first_section.blocks[6]
384
+ assert_equal 50, labeled_singleline.lineno
385
+ labeled_singleline_items = labeled_singleline.find_by :context => :list_item
386
+ assert_equal 50, labeled_singleline_items[0].lineno
387
+ assert_equal 50, labeled_singleline_items[1].lineno
388
+ assert_equal 51, labeled_singleline_items[2].lineno
389
+ assert_equal 51, labeled_singleline_items[3].lineno
390
+
391
+ labeled_multiline = first_section.blocks[7]
392
+ assert_equal 54, labeled_multiline.lineno
393
+ labeled_multiline_items = labeled_multiline.find_by :context => :list_item
394
+ assert_equal 54, labeled_multiline_items[0].lineno
395
+ assert_equal 55, labeled_multiline_items[1].lineno
396
+ assert_equal 56, labeled_multiline_items[2].lineno
397
+ assert_equal 57, labeled_multiline_items[3].lineno
398
+
399
+ qanda = first_section.blocks[8]
400
+ assert_equal 61, qanda.lineno
401
+ qanda_items = qanda.find_by :context => :list_item
402
+ assert_equal 61, qanda_items[0].lineno
403
+ assert_equal 62, qanda_items[1].lineno
404
+ assert_equal 63, qanda_items[2].lineno
405
+ assert_equal 63, qanda_items[3].lineno
406
+
407
+ mixed = first_section.blocks[9]
408
+ assert_equal 66, mixed.lineno
409
+ mixed_items = mixed.find_by(:context => :list_item) {|block| block.text? }
410
+ assert_equal 66, mixed_items[0].lineno
411
+ assert_equal 67, mixed_items[1].lineno
412
+ assert_equal 68, mixed_items[2].lineno
413
+ assert_equal 69, mixed_items[3].lineno
414
+ assert_equal 70, mixed_items[4].lineno
415
+ assert_equal 71, mixed_items[5].lineno
416
+ assert_equal 72, mixed_items[6].lineno
417
+ assert_equal 73, mixed_items[7].lineno
418
+ assert_equal 74, mixed_items[8].lineno
419
+ assert_equal 75, mixed_items[9].lineno
420
+ assert_equal 77, mixed_items[10].lineno
421
+ assert_equal 78, mixed_items[11].lineno
422
+ assert_equal 79, mixed_items[12].lineno
423
+ assert_equal 80, mixed_items[13].lineno
424
+ assert_equal 81, mixed_items[14].lineno
425
+ assert_equal 82, mixed_items[15].lineno
426
+ assert_equal 83, mixed_items[16].lineno
427
+
428
+ unordered_complex_list = first_section.blocks[10]
429
+ assert_equal 86, unordered_complex_list.lineno
430
+ unordered_complex_items = unordered_complex_list.find_by :context => :list_item
431
+ assert_equal 86, unordered_complex_items[0].lineno
432
+ assert_equal 87, unordered_complex_items[1].lineno
433
+ assert_equal 88, unordered_complex_items[2].lineno
434
+ assert_equal 92, unordered_complex_items[3].lineno
435
+ assert_equal 96, unordered_complex_items[4].lineno
436
+ end
437
+
438
+ test 'should assign correct source location if section occurs on last line of input' do
439
+ input = <<-EOS
440
+ = Document Title
441
+
442
+ == Section A
443
+
444
+ content
445
+
446
+ == Section B
447
+ EOS
448
+
449
+ doc = document_from_string input, :sourcemap => true
450
+ assert_equal [1, 3, 7], (doc.find_by :context => :section).map(&:lineno)
451
+ end
452
+
453
+ test 'should allow sourcemap option on document to be modified' do
454
+ doc = Asciidoctor.load_file fixture_path('sample.asciidoc'), :parse => false
455
+ doc.sourcemap = true
456
+ doc = doc.parse
457
+
458
+ section_1 = doc.sections[0]
459
+ assert_equal 'Section A', section_1.title
460
+ refute_nil section_1.source_location
461
+ assert_equal 'sample.asciidoc', section_1.file
462
+ assert_equal 10, section_1.lineno
463
+ end
464
+
465
+ test 'find_by should return Array of blocks anywhere in document tree that match criteria' do
466
+ input = <<-EOS
467
+ = Document Title
468
+
469
+ preamble
470
+
471
+ == Section A
472
+
473
+ paragraph
474
+
475
+ --
476
+ Exhibit A::
477
+ +
478
+ [#tiger.animal]
479
+ image::tiger.png[Tiger]
480
+ --
481
+
482
+ image::shoe.png[Shoe]
483
+
484
+ == Section B
485
+
486
+ paragraph
487
+ EOS
488
+
489
+ doc = Asciidoctor.load input
490
+ result = doc.find_by :context => :image
491
+ assert_equal 2, result.size
492
+ assert_equal :image, result[0].context
493
+ assert_equal 'tiger.png', result[0].attr('target')
494
+ assert_equal :image, result[1].context
495
+ assert_equal 'shoe.png', result[1].attr('target')
496
+ end
497
+
498
+ test 'find_by should return an empty Array if no matches are found' do
499
+ input = <<-EOS
500
+ paragraph
501
+ EOS
502
+ doc = Asciidoctor.load input
503
+ result = doc.find_by :context => :section
504
+ refute_nil result
505
+ assert_equal 0, result.size
506
+ end
507
+
508
+ test 'find_by should return Array of blocks that match style criteria' do
509
+ input = <<-EOS
510
+ [square]
511
+ * one
512
+ * two
513
+ * three
514
+
515
+ ---
516
+
517
+ * apples
518
+ * bananas
519
+ * pears
520
+ EOS
521
+
522
+ doc = Asciidoctor.load input
523
+ result = doc.find_by :context => :ulist, :style => 'square'
524
+ assert_equal 1, result.size
525
+ assert_equal :ulist, result[0].context
526
+ end
527
+
528
+ test 'find_by should return Array of blocks that match role criteria' do
529
+ input = <<-EOS
530
+ [#tiger.animal]
531
+ image::tiger.png[Tiger]
532
+
533
+ image::shoe.png[Shoe]
534
+ EOS
535
+
536
+ doc = Asciidoctor.load input
537
+ result = doc.find_by :context => :image, :role => 'animal'
538
+ assert_equal 1, result.size
539
+ assert_equal :image, result[0].context
540
+ assert_equal 'tiger.png', result[0].attr('target')
541
+ end
542
+
543
+ test 'find_by should return the document title section if context selector is :section' do
544
+ input = <<-EOS
545
+ = Document Title
546
+
547
+ preamble
548
+
549
+ == Section One
550
+
551
+ content
552
+ EOS
553
+ doc = Asciidoctor.load input
554
+ result = doc.find_by :context => :section
555
+ refute_nil result
556
+ assert_equal 2, result.size
557
+ assert_equal :section, result[0].context
558
+ assert_equal 'Document Title', result[0].title
559
+ end
560
+
561
+ test 'find_by should only return results for which the block argument yields true' do
562
+ input = <<-EOS
563
+ == Section
564
+
565
+ content
566
+
567
+ === Subsection
568
+
569
+ content
570
+ EOS
571
+ doc = Asciidoctor.load input
572
+ result = doc.find_by(:context => :section) {|sect| sect.level == 1 }
573
+ refute_nil result
574
+ assert_equal 1, result.size
575
+ assert_equal :section, result[0].context
576
+ assert_equal 'Section', result[0].title
577
+ end
578
+
579
+ test 'find_by should only return one result when matching by id' do
580
+ input = <<-EOS
581
+ == Section
582
+
583
+ content
584
+
585
+ [#subsection]
586
+ === Subsection
587
+
588
+ content
589
+ EOS
590
+ doc = Asciidoctor.load input
591
+ result = doc.find_by(:context => :section, :id => 'subsection')
592
+ refute_nil result
593
+ assert_equal 1, result.size
594
+ assert_equal :section, result[0].context
595
+ assert_equal 'Subsection', result[0].title
596
+ end
597
+
598
+ test 'find_by should return an empty Array if the id criteria matches but the block argument yields false' do
599
+ input = <<-EOS
600
+ == Section
601
+
602
+ content
603
+
604
+ [#subsection]
605
+ === Subsection
606
+
607
+ content
608
+ EOS
609
+ doc = Asciidoctor.load input
610
+ result = doc.find_by(:context => :section, :id => 'subsection') {|sect| false }
611
+ refute_nil result
612
+ assert_equal 0, result.size
613
+ end
614
+
615
+ test 'find_by should not crash if dlist entry does not have description' do
616
+ input = <<-EOS
617
+ term without description::
618
+ EOS
619
+ doc = Asciidoctor.load input
620
+ result = doc.find_by
621
+ refute_nil result
622
+ assert_equal 3, result.size
623
+ assert_kind_of Asciidoctor::Document, result[0]
624
+ assert_kind_of Asciidoctor::List, result[1]
625
+ assert_kind_of Asciidoctor::ListItem, result[2]
626
+ end
627
+
628
+ test 'timings are recorded for each step when load and convert are called separately' do
629
+ sample_input_path = fixture_path 'asciidoc_index.txt'
630
+ (Asciidoctor.load_file sample_input_path, :timings => (timings = Asciidoctor::Timings.new)).convert
631
+ refute_equal '0.00000', '%05.5f' % timings.read_parse.to_f
632
+ refute_equal '0.00000', '%05.5f' % timings.convert.to_f
633
+ refute_equal timings.read_parse, timings.total
634
+ end
635
+ end
636
+
637
+ context 'Convert' do
638
+ test 'render_file is aliased to convert_file' do
639
+ assert_equal Asciidoctor.method(:convert_file), Asciidoctor.method(:render_file)
640
+ end
641
+
642
+ test 'render is aliased to convert' do
643
+ assert_equal Asciidoctor.method(:convert), Asciidoctor.method(:render)
644
+ end
645
+
646
+ test 'should convert source document to string when to_file is false' do
647
+ sample_input_path = fixture_path('sample.asciidoc')
648
+
649
+ output = Asciidoctor.convert_file sample_input_path, :header_footer => true, :to_file => false
650
+ refute_empty output
651
+ assert_xpath '/html', output, 1
652
+ assert_xpath '/html/head', output, 1
653
+ assert_xpath '/html/body', output, 1
654
+ assert_xpath '/html/head/title[text() = "Document Title"]', output, 1
655
+ assert_xpath '/html/body/*[@id="header"]/h1[text() = "Document Title"]', output, 1
656
+ end
657
+
658
+ test 'lines in output should be separated by line feed' do
659
+ sample_input_path = fixture_path('sample.asciidoc')
660
+
661
+ output = Asciidoctor.convert_file sample_input_path, :header_footer => true, :to_file => false
662
+ refute_empty output
663
+ lines = output.split("\n")
664
+ assert_equal lines.size, output.split(/\r\n|\r|\n/).size
665
+ raw_lengths = lines.map(&:length)
666
+ trimmed_lengths = lines.map {|line| line.rstrip.length }
667
+ assert_equal raw_lengths, trimmed_lengths
668
+ end
669
+
670
+ test 'should accept attributes as array' do
671
+ sample_input_path = fixture_path('sample.asciidoc')
672
+ output = Asciidoctor.convert_file sample_input_path, :attributes => %w(sectnums idprefix idseparator=-), :to_file => false
673
+ assert_css '#section-a', output, 1
674
+ end
675
+
676
+ test 'should accept attributes as string' do
677
+ sample_input_path = fixture_path('sample.asciidoc')
678
+ output = Asciidoctor.convert_file sample_input_path, :attributes => 'sectnums idprefix idseparator=-', :to_file => false
679
+ assert_css '#section-a', output, 1
680
+ end
681
+
682
+ test 'should link to default stylesheet by default when safe mode is SECURE or greater' do
683
+ sample_input_path = fixture_path('basic.asciidoc')
684
+ output = Asciidoctor.convert_file sample_input_path, :header_footer => true, :to_file => false
685
+ assert_css 'html:root > head > link[rel="stylesheet"][href^="https://fonts.googleapis.com"]', output, 1
686
+ assert_css 'html:root > head > link[rel="stylesheet"][href="./asciidoctor.css"]', output, 1
687
+ end
688
+
689
+ test 'should embed default stylesheet by default if SafeMode is less than SECURE' do
690
+ input = <<-EOS
691
+ = Document Title
692
+
693
+ text
694
+ EOS
695
+
696
+ output = Asciidoctor.convert input, :safe => Asciidoctor::SafeMode::SERVER, :header_footer => true
697
+ assert_css 'html:root > head > link[rel="stylesheet"][href^="https://fonts.googleapis.com"]', output, 1
698
+ assert_css 'html:root > head > link[rel="stylesheet"][href="./asciidoctor.css"]', output, 0
699
+ stylenode = xmlnodes_at_css 'html:root > head > style', output, 1
700
+ styles = stylenode.content
701
+ refute_nil styles
702
+ refute_empty styles.strip
703
+ end
704
+
705
+ test 'should not allow linkcss be unset from document if SafeMode is SECURE or greater' do
706
+ input = <<-EOS
707
+ = Document Title
708
+ :linkcss!:
709
+
710
+ text
711
+ EOS
712
+
713
+ output = Asciidoctor.convert input, :header_footer => true
714
+ assert_css 'html:root > head > link[rel="stylesheet"][href^="https://fonts.googleapis.com"]', output, 1
715
+ assert_css 'html:root > head > link[rel="stylesheet"][href="./asciidoctor.css"]', output, 1
716
+ end
717
+
718
+ test 'should embed default stylesheet if linkcss is unset from API and SafeMode is SECURE or greater' do
719
+ input = <<-EOS
720
+ = Document Title
721
+
722
+ text
723
+ EOS
724
+
725
+ #[{ 'linkcss!' => '' }, { 'linkcss' => nil }, { 'linkcss' => false }].each do |attrs|
726
+ [{ 'linkcss!' => '' }, { 'linkcss' => nil }].each do |attrs|
727
+ output = Asciidoctor.convert input, :header_footer => true, :attributes => attrs
728
+ assert_css 'html:root > head > link[rel="stylesheet"][href^="https://fonts.googleapis.com"]', output, 1
729
+ assert_css 'html:root > head > link[rel="stylesheet"][href="./asciidoctor.css"]', output, 0
730
+ stylenode = xmlnodes_at_css 'html:root > head > style', output, 1
731
+ styles = stylenode.content
732
+ refute_nil styles
733
+ refute_empty styles.strip
734
+ end
735
+ end
736
+
737
+ test 'should embed default stylesheet if safe mode is less than SECURE and linkcss is unset from API' do
738
+ sample_input_path = fixture_path('basic.asciidoc')
739
+ output = Asciidoctor.convert_file sample_input_path, :header_footer => true, :to_file => false,
740
+ :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'linkcss!' => ''}
741
+ assert_css 'html:root > head > style', output, 1
742
+ stylenode = xmlnodes_at_css 'html:root > head > style', output, 1
743
+ styles = stylenode.content
744
+ refute_nil styles
745
+ refute_empty styles.strip
746
+ end
747
+
748
+ test 'should not link to stylesheet if stylesheet is unset' do
749
+ input = <<-EOS
750
+ = Document Title
751
+
752
+ text
753
+ EOS
754
+
755
+ output = Asciidoctor.convert input, :header_footer => true, :attributes => {'stylesheet!' => ''}
756
+ assert_css 'html:root > head > link[rel="stylesheet"][href^="https://fonts.googleapis.com"]', output, 0
757
+ assert_css 'html:root > head > link[rel="stylesheet"]', output, 0
758
+ end
759
+
760
+ test 'should link to custom stylesheet if specified in stylesheet attribute' do
761
+ input = <<-EOS
762
+ = Document Title
763
+
764
+ text
765
+ EOS
766
+
767
+ output = Asciidoctor.convert input, :header_footer => true, :attributes => {'stylesheet' => './custom.css'}
768
+ assert_css 'html:root > head > link[rel="stylesheet"][href^="https://fonts.googleapis.com"]', output, 0
769
+ assert_css 'html:root > head > link[rel="stylesheet"][href="./custom.css"]', output, 1
770
+
771
+ output = Asciidoctor.convert input, :header_footer => true, :attributes => {'stylesheet' => 'file:///home/username/custom.css'}
772
+ assert_css 'html:root > head > link[rel="stylesheet"][href="file:///home/username/custom.css"]', output, 1
773
+ end
774
+
775
+ test 'should resolve custom stylesheet relative to stylesdir' do
776
+ input = <<-EOS
777
+ = Document Title
778
+
779
+ text
780
+ EOS
781
+
782
+ output = Asciidoctor.convert input, :header_footer => true, :attributes => {'stylesheet' => 'custom.css', 'stylesdir' => './stylesheets'}
783
+ assert_css 'html:root > head > link[rel="stylesheet"][href="./stylesheets/custom.css"]', output, 1
784
+ end
785
+
786
+ test 'should resolve custom stylesheet to embed relative to stylesdir' do
787
+ sample_input_path = fixture_path('basic.asciidoc')
788
+ output = Asciidoctor.convert_file sample_input_path, :header_footer => true, :safe => Asciidoctor::SafeMode::SAFE, :to_file => false,
789
+ :attributes => {'stylesheet' => 'custom.css', 'stylesdir' => './stylesheets', 'linkcss!' => ''}
790
+ stylenode = xmlnodes_at_css 'html:root > head > style', output, 1
791
+ styles = stylenode.content
792
+ refute_nil styles
793
+ refute_empty styles.strip
794
+ end
795
+
796
+ test 'should convert source file and write result to adjacent file by default' do
797
+ sample_input_path = fixture_path('sample.asciidoc')
798
+ sample_output_path = fixture_path('sample.html')
799
+ begin
800
+ Asciidoctor.convert_file sample_input_path
801
+ assert File.exist?(sample_output_path)
802
+ output = IO.read(sample_output_path)
803
+ refute_empty output
804
+ assert_xpath '/html', output, 1
805
+ assert_xpath '/html/head', output, 1
806
+ assert_xpath '/html/body', output, 1
807
+ assert_xpath '/html/head/title[text() = "Document Title"]', output, 1
808
+ assert_xpath '/html/body/*[@id="header"]/h1[text() = "Document Title"]', output, 1
809
+ ensure
810
+ FileUtils.rm(sample_output_path)
811
+ end
812
+ end
813
+
814
+ test 'should convert source file and write to specified file' do
815
+ sample_input_path = fixture_path('sample.asciidoc')
816
+ sample_output_path = fixture_path('result.html')
817
+ begin
818
+ Asciidoctor.convert_file sample_input_path, :to_file => sample_output_path
819
+ assert File.exist?(sample_output_path)
820
+ output = IO.read(sample_output_path)
821
+ refute_empty output
822
+ assert_xpath '/html', output, 1
823
+ assert_xpath '/html/head', output, 1
824
+ assert_xpath '/html/body', output, 1
825
+ assert_xpath '/html/head/title[text() = "Document Title"]', output, 1
826
+ assert_xpath '/html/body/*[@id="header"]/h1[text() = "Document Title"]', output, 1
827
+ ensure
828
+ FileUtils.rm(sample_output_path)
829
+ end
830
+ end
831
+
832
+ test 'should convert source file and write to specified file in base_dir' do
833
+ sample_input_path = fixture_path('sample.asciidoc')
834
+ sample_output_path = fixture_path('result.html')
835
+ fixture_dir = fixture_path('')
836
+ begin
837
+ Asciidoctor.convert_file sample_input_path, :to_file => 'result.html', :base_dir => fixture_dir
838
+ assert File.exist?(sample_output_path)
839
+ output = IO.read(sample_output_path)
840
+ refute_empty output
841
+ assert_xpath '/html', output, 1
842
+ assert_xpath '/html/head', output, 1
843
+ assert_xpath '/html/body', output, 1
844
+ assert_xpath '/html/head/title[text() = "Document Title"]', output, 1
845
+ assert_xpath '/html/body/*[@id="header"]/h1[text() = "Document Title"]', output, 1
846
+ rescue => e
847
+ flunk e.message
848
+ ensure
849
+ FileUtils.rm(sample_output_path, :force => true)
850
+ end
851
+ end
852
+
853
+ test 'in_place option is ignored when to_file is specified' do
854
+ sample_input_path = fixture_path('sample.asciidoc')
855
+ sample_output_path = fixture_path('result.html')
856
+ begin
857
+ Asciidoctor.convert_file sample_input_path, :to_file => sample_output_path, :in_place => true
858
+ assert File.exist?(sample_output_path)
859
+ ensure
860
+ FileUtils.rm(sample_output_path) if File.exist? sample_output_path
861
+ end
862
+ end
863
+
864
+ test 'in_place option is ignored when to_dir is specified' do
865
+ sample_input_path = fixture_path('sample.asciidoc')
866
+ sample_output_path = fixture_path('sample.html')
867
+ begin
868
+ Asciidoctor.convert_file sample_input_path, :to_dir => File.dirname(sample_output_path), :in_place => true
869
+ assert File.exist?(sample_output_path)
870
+ ensure
871
+ FileUtils.rm(sample_output_path) if File.exist? sample_output_path
872
+ end
873
+ end
874
+
875
+ test 'should set outfilesuffix to match file extension of target file' do
876
+ sample_input = '{outfilesuffix}'
877
+ sample_output_path = fixture_path('result.htm')
878
+ begin
879
+ Asciidoctor.convert sample_input, :to_file => sample_output_path, :header_footer => false
880
+ assert File.exist?(sample_output_path)
881
+ output = IO.read(sample_output_path)
882
+ refute_empty output
883
+ assert_includes output, '<p>.htm</p>'
884
+ ensure
885
+ FileUtils.rm(sample_output_path)
886
+ end
887
+ end
888
+
889
+ test 'output should be relative to to_dir option' do
890
+ sample_input_path = fixture_path('sample.asciidoc')
891
+ output_dir = File.join(File.dirname(sample_input_path), 'test_output')
892
+ Dir.mkdir output_dir if !File.exist? output_dir
893
+ sample_output_path = File.join(output_dir, 'sample.html')
894
+ begin
895
+ Asciidoctor.convert_file sample_input_path, :to_dir => output_dir
896
+ assert File.exist? sample_output_path
897
+ ensure
898
+ FileUtils.rm(sample_output_path) if File.exist? sample_output_path
899
+ FileUtils.rmdir output_dir
900
+ end
901
+ end
902
+
903
+ test 'missing directories should be created if mkdirs is enabled' do
904
+ sample_input_path = fixture_path('sample.asciidoc')
905
+ output_dir = File.join(File.join(File.dirname(sample_input_path), 'test_output'), 'subdir')
906
+ sample_output_path = File.join(output_dir, 'sample.html')
907
+ begin
908
+ Asciidoctor.convert_file sample_input_path, :to_dir => output_dir, :mkdirs => true
909
+ assert File.exist? sample_output_path
910
+ ensure
911
+ FileUtils.rm(sample_output_path) if File.exist? sample_output_path
912
+ FileUtils.rmdir output_dir
913
+ FileUtils.rmdir File.dirname(output_dir)
914
+ end
915
+ end
916
+
917
+ # TODO need similar test for when to_dir is specified
918
+ test 'should raise exception if an attempt is made to overwrite input file' do
919
+ sample_input_path = fixture_path('sample.asciidoc')
920
+
921
+ assert_raises IOError do
922
+ Asciidoctor.convert_file sample_input_path, :attributes => { 'outfilesuffix' => '.asciidoc' }
923
+ end
924
+ end
925
+
926
+ test 'to_file should be relative to to_dir when both given' do
927
+ sample_input_path = fixture_path('sample.asciidoc')
928
+ base_dir = File.dirname(sample_input_path)
929
+ sample_rel_output_path = File.join('test_output', 'result.html')
930
+ output_dir = File.dirname(File.join(base_dir, sample_rel_output_path))
931
+ Dir.mkdir output_dir if !File.exist? output_dir
932
+ sample_output_path = File.join(base_dir, sample_rel_output_path)
933
+ begin
934
+ Asciidoctor.convert_file sample_input_path, :to_dir => base_dir, :to_file => sample_rel_output_path
935
+ assert File.exist? sample_output_path
936
+ ensure
937
+ FileUtils.rm(sample_output_path) if File.exist? sample_output_path
938
+ FileUtils.rmdir output_dir
939
+ end
940
+ end
941
+
942
+ test 'should not modify options argument' do
943
+ options = {
944
+ :safe => Asciidoctor::SafeMode::SAFE,
945
+ :to_file => false
946
+ }
947
+ options.freeze
948
+ sample_input_path = fixture_path('sample.asciidoc')
949
+ begin
950
+ Asciidoctor.convert_file sample_input_path, options
951
+ rescue
952
+ flunk %(options argument should not be modified)
953
+ end
954
+ end
955
+
956
+ test 'should set to_dir option to parent directory of specified output file' do
957
+ sample_input_path = fixture_path 'basic.asciidoc'
958
+ sample_output_path = fixture_path 'basic.html'
959
+ begin
960
+ doc = Asciidoctor.convert_file sample_input_path, :to_file => sample_output_path
961
+ assert_equal File.dirname(sample_output_path), doc.options[:to_dir]
962
+ ensure
963
+ FileUtils.rm(sample_output_path)
964
+ end
965
+ end
966
+
967
+ test 'should set to_dir option to parent directory of specified output directory and file' do
968
+ sample_input_path = fixture_path 'basic.asciidoc'
969
+ sample_output_path = fixture_path 'basic.html'
970
+ fixture_base_path = File.dirname sample_output_path
971
+ fixture_parent_path = File.dirname fixture_base_path
972
+ sample_output_relpath = File.join 'fixtures', 'basic.html'
973
+ begin
974
+ doc = Asciidoctor.convert_file sample_input_path, :to_dir => fixture_parent_path, :to_file => sample_output_relpath
975
+ assert_equal fixture_base_path, doc.options[:to_dir]
976
+ ensure
977
+ FileUtils.rm(sample_output_path)
978
+ end
979
+ end
980
+
981
+ test 'timings are recorded for each step' do
982
+ sample_input_path = fixture_path 'asciidoc_index.txt'
983
+ Asciidoctor.convert_file sample_input_path, :timings => (timings = Asciidoctor::Timings.new), :to_file => false
984
+ refute_equal '0.00000', '%05.5f' % timings.read_parse.to_f
985
+ refute_equal '0.00000', '%05.5f' % timings.convert.to_f
986
+ refute_equal timings.read_parse, timings.total
987
+ end
988
+ end
989
+
990
+ context 'AST' do
991
+ test 'should not crash if nil cell text is passed to Cell constructor' do
992
+ input = <<-EOS
993
+ |===
994
+ |a
995
+ |===
996
+ EOS
997
+ table = (document_from_string input).blocks[0]
998
+ cell = Asciidoctor::Table::Cell.new table.rows.body[0][0].column, nil, {}
999
+ refute cell.style
1000
+ assert_same Asciidoctor::AbstractNode::NORMAL_SUBS, cell.subs
1001
+ assert_equal '', cell.text
1002
+ end
1003
+ end
1004
+ end