asciidoctor 0.1.1 → 0.1.2

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 (53) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +1 -1
  3. data/LICENSE +2 -2
  4. data/README.adoc +461 -0
  5. data/asciidoctor.gemspec +27 -16
  6. data/compat/asciidoc.conf +139 -0
  7. data/lib/asciidoctor.rb +212 -69
  8. data/lib/asciidoctor/abstract_block.rb +41 -0
  9. data/lib/asciidoctor/abstract_node.rb +128 -81
  10. data/lib/asciidoctor/attribute_list.rb +5 -2
  11. data/lib/asciidoctor/backends/base_template.rb +16 -4
  12. data/lib/asciidoctor/backends/docbook45.rb +112 -42
  13. data/lib/asciidoctor/backends/html5.rb +206 -90
  14. data/lib/asciidoctor/block.rb +5 -5
  15. data/lib/asciidoctor/cli/invoker.rb +38 -34
  16. data/lib/asciidoctor/cli/options.rb +3 -3
  17. data/lib/asciidoctor/document.rb +115 -13
  18. data/lib/asciidoctor/helpers.rb +16 -0
  19. data/lib/asciidoctor/lexer.rb +486 -359
  20. data/lib/asciidoctor/path_resolver.rb +360 -0
  21. data/lib/asciidoctor/reader.rb +122 -23
  22. data/lib/asciidoctor/renderer.rb +1 -33
  23. data/lib/asciidoctor/section.rb +1 -1
  24. data/lib/asciidoctor/substituters.rb +103 -19
  25. data/lib/asciidoctor/version.rb +1 -1
  26. data/man/asciidoctor.1 +6 -6
  27. data/man/asciidoctor.ad +5 -3
  28. data/stylesheets/asciidoctor.css +274 -0
  29. data/test/attributes_test.rb +133 -10
  30. data/test/blocks_test.rb +302 -17
  31. data/test/document_test.rb +269 -6
  32. data/test/fixtures/basic-docinfo.html +1 -0
  33. data/test/fixtures/basic-docinfo.xml +4 -0
  34. data/test/fixtures/basic.asciidoc +4 -0
  35. data/test/fixtures/docinfo.html +1 -0
  36. data/test/fixtures/docinfo.xml +2 -0
  37. data/test/fixtures/include-file.asciidoc +22 -1
  38. data/test/fixtures/stylesheets/custom.css +3 -0
  39. data/test/invoker_test.rb +38 -6
  40. data/test/lexer_test.rb +64 -21
  41. data/test/links_test.rb +4 -0
  42. data/test/lists_test.rb +251 -12
  43. data/test/paragraphs_test.rb +225 -30
  44. data/test/paths_test.rb +174 -0
  45. data/test/reader_test.rb +89 -2
  46. data/test/sections_test.rb +518 -16
  47. data/test/substitutions_test.rb +121 -10
  48. data/test/tables_test.rb +53 -13
  49. data/test/test_helper.rb +2 -2
  50. data/test/text_test.rb +5 -5
  51. metadata +46 -50
  52. data/README.asciidoc +0 -296
  53. data/lib/asciidoctor/errors.rb +0 -5
@@ -19,6 +19,16 @@ context 'Document' do
19
19
  assert_equal Asciidoctor::SafeMode::SECURE, doc.safe
20
20
  end
21
21
 
22
+ test 'safe mode attributes are set on document' do
23
+ doc = Asciidoctor::Document.new
24
+ assert_equal Asciidoctor::SafeMode::SECURE, doc.attr('safe-mode-level')
25
+ assert_equal 'secure', doc.attr('safe-mode-name')
26
+ assert doc.attr?('safe-mode-secure')
27
+ assert !doc.attr?('safe-mode-unsafe')
28
+ assert !doc.attr?('safe-mode-safe')
29
+ assert !doc.attr?('safe-mode-server')
30
+ end
31
+
22
32
  test 'safe mode level can be set in the constructor' do
23
33
  doc = Asciidoctor::Document.new [], :safe => Asciidoctor::SafeMode::SAFE
24
34
  assert_equal Asciidoctor::SafeMode::SAFE, doc.safe
@@ -94,6 +104,7 @@ preamble
94
104
  context 'Render APIs' do
95
105
  test 'should render document to string' do
96
106
  sample_input_path = fixture_path('sample.asciidoc')
107
+
97
108
  output = Asciidoctor.render_file(sample_input_path, :header_footer => true)
98
109
  assert !output.empty?
99
110
  assert_xpath '/html', output, 1
@@ -103,6 +114,165 @@ preamble
103
114
  assert_xpath '/html/body/*[@id="header"]/h1[text() = "Document Title"]', output, 1
104
115
  end
105
116
 
117
+ test 'should include docinfo files for html backend' do
118
+ sample_input_path = fixture_path('basic.asciidoc')
119
+
120
+ output = Asciidoctor.render_file(sample_input_path,
121
+ :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo' => ''})
122
+ assert !output.empty?
123
+ assert_css 'script[src="modernizr.js"]', output, 1
124
+ assert_css 'meta[http-equiv="imagetoolbar"]', output, 0
125
+
126
+ output = Asciidoctor.render_file(sample_input_path,
127
+ :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo1' => ''})
128
+ assert !output.empty?
129
+ assert_css 'script[src="modernizr.js"]', output, 0
130
+ assert_css 'meta[http-equiv="imagetoolbar"]', output, 1
131
+
132
+ output = Asciidoctor.render_file(sample_input_path,
133
+ :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo2' => ''})
134
+ assert !output.empty?
135
+ assert_css 'script[src="modernizr.js"]', output, 1
136
+ assert_css 'meta[http-equiv="imagetoolbar"]', output, 1
137
+ end
138
+
139
+ test 'should include docinfo files for docbook backend' do
140
+ sample_input_path = fixture_path('basic.asciidoc')
141
+
142
+ output = Asciidoctor.render_file(sample_input_path,
143
+ :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo' => ''})
144
+ assert !output.empty?
145
+ assert_css 'productname', output, 0
146
+ assert_css 'copyright', output, 1
147
+
148
+ output = Asciidoctor.render_file(sample_input_path,
149
+ :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo1' => ''})
150
+ assert !output.empty?
151
+ assert_css 'productname', output, 1
152
+ assert_css 'copyright', output, 0
153
+
154
+ output = Asciidoctor.render_file(sample_input_path,
155
+ :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docinfo2' => ''})
156
+ assert !output.empty?
157
+ assert_css 'productname', output, 1
158
+ assert_css 'copyright', output, 1
159
+ end
160
+
161
+ test 'should not include docinfo files by default' do
162
+ sample_input_path = fixture_path('basic.asciidoc')
163
+
164
+ output = Asciidoctor.render_file(sample_input_path,
165
+ :header_footer => true, :safe => Asciidoctor::SafeMode::SERVER)
166
+ assert !output.empty?
167
+ assert_css 'script[src="modernizr.js"]', output, 0
168
+ assert_css 'meta[http-equiv="imagetoolbar"]', output, 0
169
+
170
+ output = Asciidoctor.render_file(sample_input_path,
171
+ :header_footer => true, :backend => 'docbook', :safe => Asciidoctor::SafeMode::SERVER)
172
+ assert !output.empty?
173
+ assert_css 'productname', output, 0
174
+ assert_css 'copyright', output, 0
175
+ end
176
+
177
+ test 'should not include docinfo files if safe mode is SECURE or greater' do
178
+ sample_input_path = fixture_path('basic.asciidoc')
179
+
180
+ output = Asciidoctor.render_file(sample_input_path,
181
+ :header_footer => true, :attributes => {'docinfo2' => ''})
182
+ assert !output.empty?
183
+ assert_css 'script[src="modernizr.js"]', output, 0
184
+ assert_css 'meta[http-equiv="imagetoolbar"]', output, 0
185
+
186
+ output = Asciidoctor.render_file(sample_input_path,
187
+ :header_footer => true, :backend => 'docbook', :attributes => {'docinfo2' => ''})
188
+ assert !output.empty?
189
+ assert_css 'productname', output, 0
190
+ assert_css 'copyright', output, 0
191
+ end
192
+
193
+ test 'should link to default stylesheet by default' do
194
+ sample_input_path = fixture_path('basic.asciidoc')
195
+ output = Asciidoctor.render_file(sample_input_path, :header_footer => true)
196
+ assert_css 'html:root > head > link[rel="stylesheet"][href="./asciidoctor.css"]', output, 1
197
+ end
198
+
199
+ test 'should link to default stylesheet by default if linkcss is unset in document' do
200
+ input = <<-EOS
201
+ = Document Title
202
+ :linkcss!:
203
+
204
+ text
205
+ EOS
206
+
207
+ output = Asciidoctor.render(input, :header_footer => true)
208
+ assert_css 'html:root > head > link[rel="stylesheet"][href="./asciidoctor.css"]', output, 1
209
+ end
210
+
211
+ test 'should link to default stylesheet by default if linkcss is unset' do
212
+ input = <<-EOS
213
+ = Document Title
214
+
215
+ text
216
+ EOS
217
+
218
+ output = Asciidoctor.render(input, :header_footer => true, :attributes => {'linkcss!' => ''})
219
+ assert_css 'html:root > head > link[rel="stylesheet"][href="./asciidoctor.css"]', output, 1
220
+ end
221
+
222
+ test 'should embed default stylesheet if safe mode is less than secure and linkcss is unset' do
223
+ sample_input_path = fixture_path('basic.asciidoc')
224
+ output = Asciidoctor.render_file(sample_input_path, :header_footer => true,
225
+ :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'linkcss!' => ''})
226
+ assert_css 'html:root > head > style', output, 1
227
+ stylenode = xmlnodes_at_css 'html:root > head > style', output, 1
228
+ styles = stylenode.first.content
229
+ assert !styles.nil?
230
+ assert !styles.strip.empty?
231
+ end
232
+
233
+ test 'should not link to stylesheet if stylesheet is unset' do
234
+ input = <<-EOS
235
+ = Document Title
236
+
237
+ text
238
+ EOS
239
+
240
+ output = Asciidoctor.render(input, :header_footer => true, :attributes => {'stylesheet!' => ''})
241
+ assert_css 'html:root > head > link[rel="stylesheet"]', output, 0
242
+ end
243
+
244
+ test 'should link to custom stylesheet if specified in stylesheet attribute' do
245
+ input = <<-EOS
246
+ = Document Title
247
+
248
+ text
249
+ EOS
250
+
251
+ output = Asciidoctor.render(input, :header_footer => true, :attributes => {'stylesheet' => './custom.css'})
252
+ assert_css 'html:root > head > link[rel="stylesheet"][href="./custom.css"]', output, 1
253
+ end
254
+
255
+ test 'should resolve custom stylesheet relative to stylesdir' do
256
+ input = <<-EOS
257
+ = Document Title
258
+
259
+ text
260
+ EOS
261
+
262
+ output = Asciidoctor.render(input, :header_footer => true, :attributes => {'stylesheet' => 'custom.css', 'stylesdir' => './stylesheets'})
263
+ assert_css 'html:root > head > link[rel="stylesheet"][href="./stylesheets/custom.css"]', output, 1
264
+ end
265
+
266
+ test 'should resolve custom stylesheet to embed relative to stylesdir' do
267
+ sample_input_path = fixture_path('basic.asciidoc')
268
+ output = Asciidoctor.render_file(sample_input_path, :header_footer => true, :safe => Asciidoctor::SafeMode::SAFE,
269
+ :attributes => {'stylesheet' => 'custom.css', 'stylesdir' => './stylesheets', 'linkcss!' => ''})
270
+ stylenode = xmlnodes_at_css 'html:root > head > style', output, 1
271
+ styles = stylenode.first.content
272
+ assert !styles.nil?
273
+ assert !styles.strip.empty?
274
+ end
275
+
106
276
  test 'should render document in place' do
107
277
  sample_input_path = fixture_path('sample.asciidoc')
108
278
  sample_output_path = fixture_path('sample.html')
@@ -219,7 +389,7 @@ preamble
219
389
  assert !renderer.nil?
220
390
  views = renderer.views
221
391
  assert !views.nil?
222
- assert_equal 30, views.size
392
+ assert_equal 33, views.size
223
393
  assert views.has_key? 'document'
224
394
  assert views['document'].is_a?(Asciidoctor::HTML5::DocumentTemplate)
225
395
  assert_equal 'ERB', views['document'].eruby.to_s
@@ -235,7 +405,7 @@ preamble
235
405
  assert !renderer.nil?
236
406
  views = renderer.views
237
407
  assert !views.nil?
238
- assert_equal 30, views.size
408
+ assert_equal 33, views.size
239
409
  assert views.has_key? 'document'
240
410
  assert views['document'].is_a?(Asciidoctor::DocBook45::DocumentTemplate)
241
411
  assert_equal 'ERB', views['document'].eruby.to_s
@@ -302,6 +472,23 @@ preamble
302
472
 
303
473
  preamble
304
474
 
475
+ == First Section
476
+ EOS
477
+ doc = document_from_string input
478
+ assert_equal 'Override', doc.doctitle
479
+ assert_nil doc.title
480
+ assert doc.has_header?
481
+ assert_equal 'Override', doc.header.title
482
+ assert_equal 'Override', doc.first_section.title
483
+ end
484
+
485
+ test 'doctitle attribute entry above header overrides header title and doctitle' do
486
+ input = <<-EOS
487
+ :doctitle: Override
488
+ = Title
489
+
490
+ preamble
491
+
305
492
  == First Section
306
493
  EOS
307
494
  doc = document_from_string input
@@ -357,14 +544,57 @@ more info...
357
544
  EOS
358
545
  output = render_string input
359
546
  assert_xpath '//*[@id="header"]/span[@id="author"][text() = "Stuart Rackham"]', output, 1
360
- assert_xpath '//*[@id="header"]/span[@id="email"][contains(text(), "founder@asciidoc.org")]', output, 1
547
+ assert_xpath '//*[@id="header"]/span[@id="email"]/a[@href="mailto:founder@asciidoc.org"][text() = "founder@asciidoc.org"]', output, 1
361
548
  assert_xpath '//*[@id="header"]/span[@id="revnumber"][text() = "version 8.6.8,"]', output, 1
362
549
  assert_xpath '//*[@id="header"]/span[@id="revdate"][text() = "2012-07-12"]', output, 1
363
550
  assert_xpath '//*[@id="header"]/span[@id="revremark"][text() = "See changelog."]', output, 1
364
551
  end
365
552
 
553
+ test 'with metadata to DocBook' do
554
+ input = <<-EOS
555
+ = AsciiDoc
556
+ Stuart Rackham <founder@asciidoc.org>
557
+ v8.6.8, 2012-07-12: See changelog.
558
+
559
+ == Version 8.6.8
560
+
561
+ more info...
562
+ EOS
563
+ output = render_string input, :backend => 'docbook'
564
+ assert_xpath '/article/articleinfo', output, 1
565
+ assert_xpath '/article/articleinfo/title[text() = "AsciiDoc"]', output, 1
566
+ assert_xpath '/article/articleinfo/date[text() = "2012-07-12"]', output, 1
567
+ assert_xpath '/article/articleinfo/author/firstname[text() = "Stuart"]', output, 1
568
+ assert_xpath '/article/articleinfo/author/surname[text() = "Rackham"]', output, 1
569
+ assert_xpath '/article/articleinfo/author/email[text() = "founder@asciidoc.org"]', output, 1
570
+ assert_xpath '/article/articleinfo/revhistory', output, 1
571
+ assert_xpath '/article/articleinfo/revhistory/revision', output, 1
572
+ assert_xpath '/article/articleinfo/revhistory/revision/revnumber[text() = "8.6.8"]', output, 1
573
+ assert_xpath '/article/articleinfo/revhistory/revision/date[text() = "2012-07-12"]', output, 1
574
+ assert_xpath '/article/articleinfo/revhistory/revision/authorinitials[text() = "SR"]', output, 1
575
+ assert_xpath '/article/articleinfo/revhistory/revision/revremark[text() = "See changelog."]', output, 1
576
+ end
577
+
578
+ test 'should create authorgroup in DocBook when multiple authors' do
579
+ input = <<-EOS
580
+ = Document Title
581
+ Doc Writer <thedoctor@asciidoc.org>; Junior Writer <junior@asciidoctor.org>
582
+
583
+ content
584
+ EOS
585
+
586
+ output = render_string input, :backend => 'docbook'
587
+ assert_xpath '//articleinfo/author', output, 0
588
+ assert_xpath '//articleinfo/authorgroup', output, 1
589
+ assert_xpath '//articleinfo/authorgroup/author', output, 2
590
+ assert_xpath '//articleinfo/authorgroup/author[1]/firstname[text() = "Doc"]', output, 1
591
+ assert_xpath '//articleinfo/authorgroup/author[2]/firstname[text() = "Junior"]', output, 1
592
+ end
593
+
366
594
  test 'with header footer' do
367
- result = render_string("= Title\n\npreamble")
595
+ doc = document_from_string "= Title\n\npreamble"
596
+ assert !doc.attr?('embedded')
597
+ result = doc.render
368
598
  assert_xpath '/html', result, 1
369
599
  assert_xpath '//*[@id="header"]', result, 1
370
600
  assert_xpath '//*[@id="header"]/h1', result, 1
@@ -373,7 +603,9 @@ more info...
373
603
  end
374
604
 
375
605
  test 'no header footer' do
376
- result = render_string("= Title\n\npreamble", :header_footer => false)
606
+ doc = document_from_string "= Title\n\npreamble", :header_footer => false
607
+ assert doc.attr?('embedded')
608
+ result = doc.render
377
609
  assert_xpath '/html', result, 0
378
610
  assert_xpath '/h1', result, 0
379
611
  assert_xpath '/*[@id="header"]', result, 0
@@ -381,7 +613,7 @@ more info...
381
613
  assert_xpath '/*[@id="preamble"]', result, 1
382
614
  end
383
615
 
384
- test 'wip enable title when no header footer' do
616
+ test 'enable title when no header footer' do
385
617
  result = render_string("= Title\n\npreamble", :header_footer => false, :attributes => {'notitle!' => ''})
386
618
  assert_xpath '/html', result, 0
387
619
  assert_xpath '/h1', result, 1
@@ -428,6 +660,24 @@ finally a reference to the second footnote footnoteref:[note2].
428
660
  text = xmlnodes_at_xpath '//div[@id="footnotes"]/div[@id="_footnote_2"]/text()', output, 1
429
661
  assert_equal '. Second footnote.', text.text.strip
430
662
  end
663
+
664
+ test 'renders footnotes block in embedded document by default' do
665
+ input = <<-EOS
666
+ Text that has supporting information{empty}footnote:[An example footnote.].
667
+ EOS
668
+
669
+ output = render_string input, :header_footer => false
670
+ assert_css '#footnotes', output, 1
671
+ end
672
+
673
+ test 'does not render footnotes block in embedded document if nofootnotes attribute is set' do
674
+ input = <<-EOS
675
+ Text that has supporting information{empty}footnote:[An example footnote.].
676
+ EOS
677
+
678
+ output = render_string input, :header_footer => false, :attributes => {'nofootnotes' => ''}
679
+ assert_css '#footnotes', output, 0
680
+ end
431
681
  end
432
682
 
433
683
  context 'Backends and Doctypes' do
@@ -499,6 +749,19 @@ chapter body
499
749
  assert_xpath '/book/simpara[text() = "text"]', result, 1
500
750
  end
501
751
 
752
+ test 'docbook45 backend parses out subtitle' do
753
+ input = <<-EOS
754
+ = Document Title: Subtitle
755
+ :doctype: book
756
+
757
+ text
758
+ EOS
759
+ result = render_string input, :backend => 'docbook45'
760
+ assert_xpath '/book', result, 1
761
+ assert_xpath '/book/bookinfo/title[text() = "Document Title"]', result, 1
762
+ assert_xpath '/book/bookinfo/subtitle[text() = "Subtitle"]', result, 1
763
+ end
764
+
502
765
  test 'should be able to set backend using :backend option key' do
503
766
  doc = Asciidoctor::Document.new([], :backend => 'html5')
504
767
  assert_equal 'html5', doc.attributes['backend']
@@ -0,0 +1 @@
1
+ <script src="modernizr.js"></script>
@@ -0,0 +1,4 @@
1
+ <copyright>
2
+ <year>2013</year>
3
+ <holder>Acme, Inc.</holder>
4
+ </copyright>
@@ -0,0 +1,4 @@
1
+ = Document Title
2
+ Doc Writer <doc.writer@asciidoc.org>
3
+
4
+ Body content.
@@ -0,0 +1 @@
1
+ <meta http-equiv="imagetoolbar" content="false">
@@ -0,0 +1,2 @@
1
+ <productname>Asciidoctor</productname>
2
+ <productnumber>1.0.0</productnumber>
@@ -1 +1,22 @@
1
- included content
1
+ first line of included content
2
+ second line of included content
3
+ third line of included content
4
+ fourth line of included content
5
+ fifth line of included content
6
+ sixth line of included content
7
+ seventh line of included content
8
+ eighth line of included content
9
+
10
+ // tag::snippetA[]
11
+ snippetA content
12
+ // end::snippetA[]
13
+
14
+ non-tagged content
15
+
16
+ // tag::snippetB[]
17
+ snippetB content
18
+ // end::snippetB[]
19
+
20
+ more non-tagged content
21
+
22
+ last line of included content
@@ -0,0 +1,3 @@
1
+ body {
2
+ color: red;
3
+ }
@@ -110,7 +110,7 @@ context 'Invoker' do
110
110
  assert_xpath '/html/head/title[text() = "Document Title"]', output, 1
111
111
  assert_xpath '/html/body/*[@id="header"]/h1[text() = "Document Title"]', output, 1
112
112
  ensure
113
- FileUtils::rm(sample_outpath)
113
+ FileUtils::rm_f(sample_outpath)
114
114
  end
115
115
  end
116
116
 
@@ -119,12 +119,14 @@ context 'Invoker' do
119
119
  sample_outpath = File.join(destination_path, 'sample.html')
120
120
  begin
121
121
  FileUtils::mkdir_p(destination_path)
122
+ # QUESTION should -D be relative to working directory or source directory?
122
123
  invoker = invoke_cli %w(-D test/test_output)
124
+ #invoker = invoke_cli %w(-D ../../test/test_output)
123
125
  doc = invoker.document
124
126
  assert_equal sample_outpath, doc.attr('outfile')
125
127
  assert File.exist?(sample_outpath)
126
128
  ensure
127
- FileUtils::rm(sample_outpath)
129
+ FileUtils::rm_f(sample_outpath)
128
130
  FileUtils::rmdir(destination_path)
129
131
  end
130
132
  end
@@ -137,7 +139,21 @@ context 'Invoker' do
137
139
  assert_equal sample_outpath, doc.attr('outfile')
138
140
  assert File.exist?(sample_outpath)
139
141
  ensure
140
- FileUtils::rm(sample_outpath)
142
+ FileUtils::rm_f(sample_outpath)
143
+ end
144
+ end
145
+
146
+ test 'should copy default css to target directory if copycss is specified' do
147
+ sample_outpath = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'sample-output.html'))
148
+ default_stylesheet = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'asciidoctor.css'))
149
+ begin
150
+ invoker = invoke_cli %W(-o #{sample_outpath} -a copycss)
151
+ invoker.document
152
+ assert File.exist?(sample_outpath)
153
+ assert File.exist?(default_stylesheet)
154
+ ensure
155
+ FileUtils::rm_f(sample_outpath)
156
+ FileUtils::rm_f(default_stylesheet)
141
157
  end
142
158
  end
143
159
 
@@ -149,17 +165,33 @@ context 'Invoker' do
149
165
  end
150
166
 
151
167
  test 'should not compact output by default' do
152
- invoker = invoke_cli_to_buffer(%w(-s -o -), '-') { 'content' }
168
+ # NOTE we are relying on the fact that the template leaves blank lines
169
+ # this will always fail when using a template engine which strips blank lines by default
170
+ invoker = invoke_cli_to_buffer(%w(-o -), '-') { '* content' }
153
171
  output = invoker.read_output
154
172
  assert_match(/\n[[:blank:]]*\n/, output)
155
173
  end
156
174
 
157
175
  test 'should compact output if specified' do
158
- invoker = invoke_cli_to_buffer(%w(-C -s -o -), '-') { 'content' }
176
+ # NOTE we are relying on the fact that the template leaves blank lines
177
+ # this will always succeed when using a template engine which strips blank lines by default
178
+ invoker = invoke_cli_to_buffer(%w(-C -s -o -), '-') { '* content' }
159
179
  output = invoker.read_output
160
180
  assert_no_match(/\n[[:blank:]]*\n/, output)
161
181
  end
162
182
 
183
+ test 'should output a trailing endline to stdout' do
184
+ invoker = nil
185
+ output = nil
186
+ redirect_streams do |stdout, stderr|
187
+ invoker = invoke_cli %w(-o -)
188
+ output = stdout.string
189
+ end
190
+ assert !invoker.nil?
191
+ assert !output.nil?
192
+ assert output.end_with?("\n")
193
+ end
194
+
163
195
  test 'should set backend to html5 if specified' do
164
196
  invoker = invoke_cli_to_buffer %w(-b html5 -o -)
165
197
  doc = invoker.document
@@ -215,7 +247,7 @@ context 'Invoker' do
215
247
  doc = invoker.document
216
248
  assert_equal '', doc.attr('icons')
217
249
  output = invoker.read_output
218
- assert_xpath '//*[@class="admonitionblock"]//img[@alt="Note"]', output, 1
250
+ assert_xpath '//*[@class="admonitionblock note"]//img[@alt="Note"]', output, 1
219
251
  end
220
252
 
221
253
  test 'should unset attribute ending in bang' do