asciidoctor 0.1.3 → 0.1.4

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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +387 -0
  3. data/README.adoc +358 -348
  4. data/asciidoctor.gemspec +30 -9
  5. data/bin/asciidoctor +3 -0
  6. data/bin/asciidoctor-safe +3 -0
  7. data/compat/asciidoc.conf +76 -4
  8. data/lib/asciidoctor.rb +174 -79
  9. data/lib/asciidoctor/abstract_block.rb +131 -101
  10. data/lib/asciidoctor/abstract_node.rb +108 -26
  11. data/lib/asciidoctor/attribute_list.rb +1 -1
  12. data/lib/asciidoctor/backends/_stylesheets.rb +204 -62
  13. data/lib/asciidoctor/backends/base_template.rb +11 -22
  14. data/lib/asciidoctor/backends/docbook45.rb +158 -163
  15. data/lib/asciidoctor/backends/docbook5.rb +103 -0
  16. data/lib/asciidoctor/backends/html5.rb +662 -445
  17. data/lib/asciidoctor/block.rb +54 -44
  18. data/lib/asciidoctor/cli/invoker.rb +41 -20
  19. data/lib/asciidoctor/cli/options.rb +66 -20
  20. data/lib/asciidoctor/debug.rb +1 -1
  21. data/lib/asciidoctor/document.rb +265 -100
  22. data/lib/asciidoctor/extensions.rb +443 -0
  23. data/lib/asciidoctor/helpers.rb +38 -6
  24. data/lib/asciidoctor/inline.rb +5 -5
  25. data/lib/asciidoctor/lexer.rb +532 -250
  26. data/lib/asciidoctor/{list_item.rb → list.rb} +33 -13
  27. data/lib/asciidoctor/path_resolver.rb +28 -2
  28. data/lib/asciidoctor/reader.rb +814 -455
  29. data/lib/asciidoctor/renderer.rb +128 -42
  30. data/lib/asciidoctor/section.rb +55 -41
  31. data/lib/asciidoctor/substituters.rb +380 -107
  32. data/lib/asciidoctor/table.rb +40 -30
  33. data/lib/asciidoctor/version.rb +1 -1
  34. data/man/asciidoctor.1 +32 -96
  35. data/man/{asciidoctor.ad → asciidoctor.adoc} +57 -48
  36. data/test/attributes_test.rb +200 -27
  37. data/test/blocks_test.rb +361 -22
  38. data/test/document_test.rb +496 -81
  39. data/test/extensions_test.rb +448 -0
  40. data/test/fixtures/basic-docinfo-footer.html +6 -0
  41. data/test/fixtures/basic-docinfo-footer.xml +8 -0
  42. data/test/fixtures/basic-docinfo.xml +3 -3
  43. data/test/fixtures/basic.asciidoc +1 -0
  44. data/test/fixtures/child-include.adoc +5 -0
  45. data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +6 -0
  46. data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +1 -0
  47. data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +3 -0
  48. data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +5 -0
  49. data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +6 -0
  50. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +3 -0
  51. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +5 -0
  52. data/test/fixtures/docinfo-footer.html +1 -0
  53. data/test/fixtures/docinfo-footer.xml +9 -0
  54. data/test/fixtures/docinfo.xml +1 -0
  55. data/test/fixtures/grandchild-include.adoc +3 -0
  56. data/test/fixtures/parent-include-restricted.adoc +5 -0
  57. data/test/fixtures/parent-include.adoc +5 -0
  58. data/test/invoker_test.rb +82 -8
  59. data/test/lexer_test.rb +21 -3
  60. data/test/links_test.rb +34 -2
  61. data/test/lists_test.rb +304 -7
  62. data/test/options_test.rb +19 -3
  63. data/test/paragraphs_test.rb +13 -0
  64. data/test/paths_test.rb +22 -0
  65. data/test/preamble_test.rb +20 -0
  66. data/test/reader_test.rb +1096 -644
  67. data/test/renderer_test.rb +152 -12
  68. data/test/sections_test.rb +417 -76
  69. data/test/substitutions_test.rb +339 -138
  70. data/test/tables_test.rb +109 -4
  71. data/test/test_helper.rb +79 -13
  72. data/test/text_test.rb +111 -11
  73. metadata +54 -18
@@ -1,22 +1,162 @@
1
1
  require 'test_helper'
2
+ require 'tilt'
2
3
 
3
4
  context 'Renderer' do
4
5
 
5
- test 'should extract view mapping from built-in template with one segment and backend' do
6
- view_name, view_backend = Asciidoctor::Renderer.extract_view_mapping('Asciidoctor::HTML5::DocumentTemplate')
7
- assert_equal 'document', view_name
8
- assert_equal 'html5', view_backend
6
+ context 'View mapping' do
7
+ test 'should extract view mapping from built-in template with one segment and backend' do
8
+ view_name, view_backend = Asciidoctor::Renderer.extract_view_mapping('Asciidoctor::HTML5::DocumentTemplate')
9
+ assert_equal 'document', view_name
10
+ assert_equal 'html5', view_backend
11
+ end
12
+
13
+ test 'should extract view mapping from built-in template with two segments and backend' do
14
+ view_name, view_backend = Asciidoctor::Renderer.extract_view_mapping('Asciidoctor::DocBook45::BlockSidebarTemplate')
15
+ assert_equal 'block_sidebar', view_name
16
+ assert_equal 'docbook45', view_backend
17
+ end
18
+
19
+ test 'should extract view mapping from built-in template without backend' do
20
+ view_name, view_backend = Asciidoctor::Renderer.extract_view_mapping('Asciidoctor::DocumentTemplate')
21
+ assert_equal 'document', view_name
22
+ assert view_backend.nil?
23
+ end
9
24
  end
10
25
 
11
- test 'should extract view mapping from built-in template with two segments and backend' do
12
- view_name, view_backend = Asciidoctor::Renderer.extract_view_mapping('Asciidoctor::DocBook45::BlockSidebarTemplate')
13
- assert_equal 'block_sidebar', view_name
14
- assert_equal 'docbook45', view_backend
26
+ context 'View options' do
27
+ test 'should set Haml format to html5 for html5 backend' do
28
+ doc = Asciidoctor::Document.new [], :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml'), :template_cache => false
29
+ assert doc.renderer.views['block_paragraph'].is_a? Tilt::HamlTemplate
30
+ assert_equal :html5, doc.renderer.views['block_paragraph'].options[:format]
31
+ end
32
+
33
+ test 'should set Haml format to xhtml for docbook backend' do
34
+ doc = Asciidoctor::Document.new [], :backend => 'docbook45', :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml'), :template_cache => false
35
+ assert doc.renderer.views['block_paragraph'].is_a? Tilt::HamlTemplate
36
+ assert_equal :xhtml, doc.renderer.views['block_paragraph'].options[:format]
37
+ end
15
38
  end
16
39
 
17
- test 'should extract view mapping from built-in template without backend' do
18
- view_name, view_backend = Asciidoctor::Renderer.extract_view_mapping('Asciidoctor::DocumentTemplate')
19
- assert_equal 'document', view_name
20
- assert view_backend.nil?
40
+ context 'Custom backends' do
41
+ test 'should load Haml templates for default backend' do
42
+ doc = Asciidoctor::Document.new [], :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml'), :template_cache => false
43
+ assert doc.renderer.views['block_paragraph'].is_a? Tilt::HamlTemplate
44
+ assert doc.renderer.views['block_paragraph'].file.end_with? 'block_paragraph.html.haml'
45
+ assert doc.renderer.views['block_sidebar'].is_a? Tilt::HamlTemplate
46
+ assert doc.renderer.views['block_sidebar'].file.end_with? 'block_sidebar.html.haml'
47
+ end
48
+
49
+ test 'should load Haml templates for docbook45 backend' do
50
+ doc = Asciidoctor::Document.new [], :backend => 'docbook45', :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml'), :template_cache => false
51
+ assert doc.renderer.views['block_paragraph'].is_a? Tilt::HamlTemplate
52
+ assert doc.renderer.views['block_paragraph'].file.end_with? 'block_paragraph.xml.haml'
53
+ end
54
+
55
+ test 'should use Haml templates in place of built-in templates' do
56
+ input = <<-EOS
57
+ = Document Title
58
+ Author Name
59
+
60
+ == Section One
61
+
62
+ Sample paragraph
63
+
64
+ .Related
65
+ ****
66
+ Sidebar content
67
+ ****
68
+ EOS
69
+
70
+ output = render_embedded_string input, :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml'), :template_cache => false
71
+ assert_xpath '/*[@class="sect1"]/*[@class="sectionbody"]/p', output, 1
72
+ assert_xpath '//aside', output, 1
73
+ assert_xpath '/*[@class="sect1"]/*[@class="sectionbody"]/p/following-sibling::aside', output, 1
74
+ assert_xpath '//aside/header/h1[text()="Related"]', output, 1
75
+ assert_xpath '//aside/header/following-sibling::p[text()="Sidebar content"]', output, 1
76
+ end
77
+
78
+ test 'should use built-in global cache to cache templates' do
79
+ # clear out any cache, just to be sure
80
+ Asciidoctor::Renderer.reset_global_cache
81
+
82
+ template_dir = File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml')
83
+ doc = Asciidoctor::Document.new [], :template_dir => template_dir
84
+ doc.renderer
85
+ template_cache = Asciidoctor::Renderer.global_cache
86
+ assert template_cache.is_a? Asciidoctor::TemplateCache
87
+ cache = template_cache.cache
88
+ assert_not_nil cache
89
+ assert cache.size > 0
90
+
91
+ # ensure we don't scan a second time (using the view option hash to mark the cached view object)
92
+ template_path = Asciidoctor::PathResolver.new.system_path(File.join(template_dir, 'html5', 'block_paragraph.html.haml'), nil)
93
+ view = template_cache.fetch(:view, template_path)
94
+ view.options[:foo] = 'bar'
95
+ doc = Asciidoctor::Document.new [], :template_dir => template_dir
96
+ doc.renderer
97
+ template_cache = Asciidoctor::Renderer.global_cache
98
+ view = template_cache.fetch(:view, template_path)
99
+ assert_equal 'bar', view.options[:foo]
100
+
101
+ # clean up
102
+ Asciidoctor::Renderer.reset_global_cache
103
+ end
104
+
105
+ test 'should use custom cache to cache templates' do
106
+ template_dir = File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml')
107
+ template_path = Asciidoctor::PathResolver.new.system_path(File.join(template_dir, 'html5', 'block_paragraph.html.haml'), nil)
108
+ doc = Asciidoctor::Document.new [], :template_dir => template_dir,
109
+ :template_cache => Asciidoctor::TemplateCache.new
110
+ template_cache = doc.renderer.cache
111
+ assert_not_nil template_cache
112
+ cache = template_cache.cache
113
+ assert_not_nil cache
114
+ assert cache.size > 0
115
+ view = template_cache.fetch(:view, template_path)
116
+ assert view.is_a? Tilt::HamlTemplate
117
+ end
118
+
119
+ test 'should be able to disable template cache' do
120
+ doc = Asciidoctor::Document.new [], :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'haml'),
121
+ :template_cache => false
122
+ assert_nil doc.renderer.cache
123
+ end
124
+
125
+ test 'should load Slim templates for default backend' do
126
+ doc = Asciidoctor::Document.new [], :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'slim'), :template_cache => false
127
+ assert doc.renderer.views['block_paragraph'].is_a? Slim::Template
128
+ assert doc.renderer.views['block_paragraph'].file.end_with? 'block_paragraph.html.slim'
129
+ assert doc.renderer.views['block_sidebar'].is_a? Slim::Template
130
+ assert doc.renderer.views['block_sidebar'].file.end_with? 'block_sidebar.html.slim'
131
+ end
132
+
133
+ test 'should load Slim templates for docbook45 backend' do
134
+ doc = Asciidoctor::Document.new [], :backend => 'docbook45', :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'slim'), :template_cache => false
135
+ assert doc.renderer.views['block_paragraph'].is_a? Slim::Template
136
+ assert doc.renderer.views['block_paragraph'].file.end_with? 'block_paragraph.xml.slim'
137
+ end
138
+
139
+ test 'should use Slim templates in place of built-in templates' do
140
+ input = <<-EOS
141
+ = Document Title
142
+ Author Name
143
+
144
+ == Section One
145
+
146
+ Sample paragraph
147
+
148
+ .Related
149
+ ****
150
+ Sidebar content
151
+ ****
152
+ EOS
153
+
154
+ output = render_embedded_string input, :template_dir => File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends', 'slim'), :template_cache => false
155
+ assert_xpath '/*[@class="sect1"]/*[@class="sectionbody"]/p', output, 1
156
+ assert_xpath '//aside', output, 1
157
+ assert_xpath '/*[@class="sect1"]/*[@class="sectionbody"]/p/following-sibling::aside', output, 1
158
+ assert_xpath '//aside/header/h1[text()="Related"]', output, 1
159
+ assert_xpath '//aside/header/following-sibling::p[text()="Sidebar content"]', output, 1
160
+ end
21
161
  end
22
162
  end
@@ -18,6 +18,11 @@ context 'Sections' do
18
18
  assert_equal '_section_one', sec.id
19
19
  end
20
20
 
21
+ test 'synthetic id removes entities' do
22
+ sec = block_from_string('== Ben & Jerry &#34;Ice Cream Brothers&#34;')
23
+ assert_equal '_ben_jerry_ice_cream_brothers', sec.id
24
+ end
25
+
21
26
  test 'synthetic id prefix can be customized' do
22
27
  sec = block_from_string(":idprefix: id_\n\n== Section One")
23
28
  assert_equal 'id_section_one', sec.id
@@ -28,6 +33,11 @@ context 'Sections' do
28
33
  assert_equal 'section_one', sec.id
29
34
  end
30
35
 
36
+ test 'synthetic id prefix is stripped from beginning of id if set to blank' do
37
+ sec = block_from_string(":idprefix:\n\n== & More")
38
+ assert_equal 'more', sec.id
39
+ end
40
+
31
41
  test 'synthetic id separator can be customized' do
32
42
  sec = block_from_string(":idseparator: -\n\n== Section One")
33
43
  assert_equal '_section-one', sec.id
@@ -97,6 +107,20 @@ text
97
107
  assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string(title + "\n" + chars + "\n")
98
108
  end
99
109
 
110
+ test 'document title with multiline syntax and unicode characters' do
111
+ input = <<-EOS
112
+ AsciiDoc Writer’s Guide
113
+ =======================
114
+ Author Name
115
+
116
+ preamble
117
+ EOS
118
+
119
+ result = render_string input
120
+ assert_xpath '//h1', result, 1
121
+ assert_xpath '//h1[text()="AsciiDoc Writer’s Guide"]', result, 1
122
+ end
123
+
100
124
  test "not enough chars for a multiline document title" do
101
125
  title = "My Title"
102
126
  chars = "=" * (title.length - 2)
@@ -402,7 +426,7 @@ text in standalone
402
426
  output, errors = nil
403
427
  redirect_streams do |stdout, stderr|
404
428
  output = render_string input
405
- errors = stdout.string
429
+ errors = stderr.string
406
430
  end
407
431
 
408
432
  assert !errors.empty?
@@ -492,22 +516,19 @@ Standalone preamble.
492
516
 
493
517
  context 'Section Numbering' do
494
518
  test 'should create section number with one entry for level 1' do
495
- sect1 = Asciidoctor::Section.new(nil)
496
- sect1.level = 1
519
+ sect1 = Asciidoctor::Section.new
497
520
  assert_equal '1.', sect1.sectnum
498
521
  end
499
522
 
500
523
  test 'should create section number with two entries for level 2' do
501
- sect1 = Asciidoctor::Section.new(nil)
502
- sect1.level = 1
524
+ sect1 = Asciidoctor::Section.new
503
525
  sect1_1 = Asciidoctor::Section.new(sect1)
504
526
  sect1 << sect1_1
505
527
  assert_equal '1.1.', sect1_1.sectnum
506
528
  end
507
529
 
508
530
  test 'should create section number with three entries for level 3' do
509
- sect1 = Asciidoctor::Section.new(nil)
510
- sect1.level = 1
531
+ sect1 = Asciidoctor::Section.new
511
532
  sect1_1 = Asciidoctor::Section.new(sect1)
512
533
  sect1 << sect1_1
513
534
  sect1_1_1 = Asciidoctor::Section.new(sect1_1)
@@ -516,8 +537,7 @@ Standalone preamble.
516
537
  end
517
538
 
518
539
  test 'should create section number for second section in level' do
519
- sect1 = Asciidoctor::Section.new(nil)
520
- sect1.level = 1
540
+ sect1 = Asciidoctor::Section.new
521
541
  sect1_1 = Asciidoctor::Section.new(sect1)
522
542
  sect1 << sect1_1
523
543
  sect1_2 = Asciidoctor::Section.new(sect1)
@@ -526,8 +546,7 @@ Standalone preamble.
526
546
  end
527
547
 
528
548
  test 'sectnum should use specified delimiter and append string' do
529
- sect1 = Asciidoctor::Section.new(nil)
530
- sect1.level = 1
549
+ sect1 = Asciidoctor::Section.new
531
550
  sect1_1 = Asciidoctor::Section.new(sect1)
532
551
  sect1 << sect1_1
533
552
  sect1_1_1 = Asciidoctor::Section.new(sect1_1)
@@ -596,6 +615,191 @@ paragraph
596
615
  assert_equal 2, doc.blocks[1].blocks[1].level
597
616
  assert_equal 2, doc.blocks[1].blocks[1].blocks[0].level
598
617
  end
618
+
619
+ test 'section numbers should not increment when numbered attribute is turned off within document' do
620
+ input = <<-EOS
621
+ = Document Title
622
+ :numbered:
623
+
624
+ :numbered!:
625
+
626
+ == Colophon Section
627
+
628
+ == Another Colophon Section
629
+
630
+ == Final Colophon Section
631
+
632
+ :numbered:
633
+
634
+ == Section One
635
+
636
+ === Section One Subsection
637
+
638
+ == Section Two
639
+
640
+ == Section Three
641
+ EOS
642
+
643
+ output = render_string input
644
+ assert_xpath '//h1[text()="Document Title"]', output, 1
645
+ assert_xpath '//h2[@id="_colophon_section"][text()="Colophon Section"]', output, 1
646
+ assert_xpath '//h2[@id="_another_colophon_section"][text()="Another Colophon Section"]', output, 1
647
+ assert_xpath '//h2[@id="_final_colophon_section"][text()="Final Colophon Section"]', output, 1
648
+ assert_xpath '//h2[@id="_section_one"][text()="1. Section One"]', output, 1
649
+ assert_xpath '//h3[@id="_section_one_subsection"][text()="1.1. Section One Subsection"]', output, 1
650
+ assert_xpath '//h2[@id="_section_two"][text()="2. Section Two"]', output, 1
651
+ assert_xpath '//h2[@id="_section_three"][text()="3. Section Three"]', output, 1
652
+ end
653
+
654
+ test 'section numbers can be toggled even if numbered attribute is enable via the API' do
655
+ input = <<-EOS
656
+ = Document Title
657
+
658
+ :numbered!:
659
+
660
+ == Colophon Section
661
+
662
+ == Another Colophon Section
663
+
664
+ == Final Colophon Section
665
+
666
+ :numbered:
667
+
668
+ == Section One
669
+
670
+ === Section One Subsection
671
+
672
+ == Section Two
673
+
674
+ == Section Three
675
+ EOS
676
+
677
+ output = render_string input, :attributes => {'numbered' => ''}
678
+ assert_xpath '//h1[text()="Document Title"]', output, 1
679
+ assert_xpath '//h2[@id="_colophon_section"][text()="Colophon Section"]', output, 1
680
+ assert_xpath '//h2[@id="_another_colophon_section"][text()="Another Colophon Section"]', output, 1
681
+ assert_xpath '//h2[@id="_final_colophon_section"][text()="Final Colophon Section"]', output, 1
682
+ assert_xpath '//h2[@id="_section_one"][text()="1. Section One"]', output, 1
683
+ assert_xpath '//h3[@id="_section_one_subsection"][text()="1.1. Section One Subsection"]', output, 1
684
+ assert_xpath '//h2[@id="_section_two"][text()="2. Section Two"]', output, 1
685
+ assert_xpath '//h2[@id="_section_three"][text()="3. Section Three"]', output, 1
686
+ end
687
+
688
+ test 'section numbers cannot be toggled even if numbered attribute is disabled via the API' do
689
+ input = <<-EOS
690
+ = Document Title
691
+
692
+ :numbered!:
693
+
694
+ == Colophon Section
695
+
696
+ == Another Colophon Section
697
+
698
+ == Final Colophon Section
699
+
700
+ :numbered:
701
+
702
+ == Section One
703
+
704
+ === Section One Subsection
705
+
706
+ == Section Two
707
+
708
+ == Section Three
709
+ EOS
710
+
711
+ output = render_string input, :attributes => {'numbered!' => ''}
712
+ assert_xpath '//h1[text()="Document Title"]', output, 1
713
+ assert_xpath '//h2[@id="_colophon_section"][text()="Colophon Section"]', output, 1
714
+ assert_xpath '//h2[@id="_another_colophon_section"][text()="Another Colophon Section"]', output, 1
715
+ assert_xpath '//h2[@id="_final_colophon_section"][text()="Final Colophon Section"]', output, 1
716
+ assert_xpath '//h2[@id="_section_one"][text()="Section One"]', output, 1
717
+ assert_xpath '//h3[@id="_section_one_subsection"][text()="Section One Subsection"]', output, 1
718
+ assert_xpath '//h2[@id="_section_two"][text()="Section Two"]', output, 1
719
+ assert_xpath '//h2[@id="_section_three"][text()="Section Three"]', output, 1
720
+ end
721
+
722
+ # NOTE AsciiDoc fails this test because it does not properly check for a None value when looking up the numbered attribute
723
+ test 'section numbers should not increment until numbered attribute is turned back on' do
724
+ input = <<-EOS
725
+ = Document Title
726
+ :numbered!:
727
+
728
+ == Colophon Section
729
+
730
+ == Another Colophon Section
731
+
732
+ == Final Colophon Section
733
+
734
+ :numbered:
735
+
736
+ == Section One
737
+
738
+ === Section One Subsection
739
+
740
+ == Section Two
741
+
742
+ == Section Three
743
+ EOS
744
+
745
+ output = render_string input
746
+ assert_xpath '//h1[text()="Document Title"]', output, 1
747
+ assert_xpath '//h2[@id="_colophon_section"][text()="Colophon Section"]', output, 1
748
+ assert_xpath '//h2[@id="_another_colophon_section"][text()="Another Colophon Section"]', output, 1
749
+ assert_xpath '//h2[@id="_final_colophon_section"][text()="Final Colophon Section"]', output, 1
750
+ assert_xpath '//h2[@id="_section_one"][text()="1. Section One"]', output, 1
751
+ assert_xpath '//h3[@id="_section_one_subsection"][text()="1.1. Section One Subsection"]', output, 1
752
+ assert_xpath '//h2[@id="_section_two"][text()="2. Section Two"]', output, 1
753
+ assert_xpath '//h2[@id="_section_three"][text()="3. Section Three"]', output, 1
754
+ end
755
+
756
+ test 'table with asciidoc content should not disable numbering of subsequent sections' do
757
+ input = <<-EOS
758
+ = Document Title
759
+ :numbered:
760
+
761
+ preamble
762
+
763
+ == Section One
764
+
765
+ |===
766
+ a|content
767
+ |===
768
+
769
+ == Section Two
770
+
771
+ content
772
+ EOS
773
+
774
+ output = render_string input
775
+ assert_xpath '//h2[@id="_section_one"]', output, 1
776
+ assert_xpath '//h2[@id="_section_one"][text()="1. Section One"]', output, 1
777
+ assert_xpath '//h2[@id="_section_two"]', output, 1
778
+ assert_xpath '//h2[@id="_section_two"][text()="2. Section Two"]', output, 1
779
+ end
780
+
781
+ test 'should not number parts when doctype is book' do
782
+ input = <<-EOS
783
+ = Document Title
784
+ :doctype: book
785
+ :numbered:
786
+
787
+ = Part 1
788
+
789
+ == Part 1: Chapter 1
790
+
791
+ = Part 2
792
+
793
+ == Part 2: Chapter 1
794
+ EOS
795
+
796
+ output = render_string input
797
+ assert_xpath '(//h1)[1][text()="Document Title"]', output, 1
798
+ assert_xpath '(//h1)[2][text()="Part 1"]', output, 1
799
+ assert_xpath '(//h1)[3][text()="Part 2"]', output, 1
800
+ assert_xpath '(//h2)[1][text()="1. Part 1: Chapter 1"]', output, 1
801
+ assert_xpath '(//h2)[2][text()="1. Part 2: Chapter 1"]', output, 1
802
+ end
599
803
  end
600
804
 
601
805
  context 'Links and anchors' do
@@ -703,9 +907,85 @@ text
703
907
  assert_xpath '//h5[text()="Level_4"]', output, 1
704
908
  end
705
909
 
910
+ test 'should not number sections or subsections in regions where numbered is off' do
911
+ input = <<-EOS
912
+ :numbered:
913
+
914
+ == Section One
915
+
916
+ :numbered!:
917
+
918
+ [appendix]
919
+ == Attribute Options
920
+
921
+ Details
922
+
923
+ [appendix]
924
+ == Migration
925
+
926
+ Details
927
+
928
+ === Gotchas
929
+
930
+ Details
931
+
932
+ [glossary]
933
+ == Glossary
934
+
935
+ Terms
936
+ EOS
937
+
938
+ output = render_embedded_string input
939
+ assert_xpath '(//h2)[1][text()="1. Section One"]', output, 1
940
+ assert_xpath '(//h2)[2][text()="Appendix A: Attribute Options"]', output, 1
941
+ assert_xpath '(//h2)[3][text()="Appendix B: Migration"]', output, 1
942
+ assert_xpath '(//h3)[1][text()="Gotchas"]', output, 1
943
+ assert_xpath '(//h2)[4][text()="Glossary"]', output, 1
944
+ end
945
+
946
+ test 'should not number sections or subsections in toc in regions where numbered is off' do
947
+ input = <<-EOS
948
+ :numbered:
949
+ :toc:
950
+
951
+ == Section One
952
+
953
+ :numbered!:
954
+
955
+ [appendix]
956
+ == Attribute Options
957
+
958
+ Details
959
+
960
+ [appendix]
961
+ == Migration
962
+
963
+ Details
964
+
965
+ === Gotchas
966
+
967
+ Details
968
+
969
+ [glossary]
970
+ == Glossary
971
+
972
+ Terms
973
+ EOS
974
+
975
+ output = render_string input
976
+ assert_xpath '//*[@id="toc"]/ul//li/a[text()="1. Section One"]', output, 1
977
+ assert_xpath '//*[@id="toc"]/ul//li/a[text()="Appendix A: Attribute Options"]', output, 1
978
+ assert_xpath '//*[@id="toc"]/ul//li/a[text()="Appendix B: Migration"]', output, 1
979
+ assert_xpath '//*[@id="toc"]/ul//li/a[text()="Gotchas"]', output, 1
980
+ assert_xpath '//*[@id="toc"]/ul//li/a[text()="Glossary"]', output, 1
981
+ end
982
+
983
+ # reenable once we have :specialnumbered!: implemented
984
+ =begin
706
985
  test 'should not number special sections or subsections' do
707
986
  input = <<-EOS
708
987
  :numbered:
988
+ :specialnumbered!:
709
989
 
710
990
  == Section One
711
991
 
@@ -740,6 +1020,7 @@ Terms
740
1020
  test 'should not number special sections or subsections in toc' do
741
1021
  input = <<-EOS
742
1022
  :numbered:
1023
+ :specialnumbered!:
743
1024
  :toc:
744
1025
 
745
1026
  == Section One
@@ -765,12 +1046,13 @@ Terms
765
1046
  EOS
766
1047
 
767
1048
  output = render_string input
768
- assert_xpath '//*[@id="toc"]/ol//li/a[text()="1. Section One"]', output, 1
769
- assert_xpath '//*[@id="toc"]/ol//li/a[text()="Appendix A: Attribute Options"]', output, 1
770
- assert_xpath '//*[@id="toc"]/ol//li/a[text()="Appendix B: Migration"]', output, 1
771
- assert_xpath '//*[@id="toc"]/ol//li/a[text()="Gotchas"]', output, 1
772
- assert_xpath '//*[@id="toc"]/ol//li/a[text()="Glossary"]', output, 1
1049
+ assert_xpath '//*[@id="toc"]/ul//li/a[text()="1. Section One"]', output, 1
1050
+ assert_xpath '//*[@id="toc"]/ul//li/a[text()="Appendix A: Attribute Options"]', output, 1
1051
+ assert_xpath '//*[@id="toc"]/ul//li/a[text()="Appendix B: Migration"]', output, 1
1052
+ assert_xpath '//*[@id="toc"]/ul//li/a[text()="Gotchas"]', output, 1
1053
+ assert_xpath '//*[@id="toc"]/ul//li/a[text()="Glossary"]', output, 1
773
1054
  end
1055
+ =end
774
1056
 
775
1057
  test 'level 0 special sections in multipart book should be rendered as level 1' do
776
1058
  input = <<-EOS
@@ -1050,18 +1332,16 @@ That's all she wrote!
1050
1332
  output = render_string input
1051
1333
  assert_xpath '//*[@id="header"]//*[@id="toc"][@class="toc"]', output, 1
1052
1334
  assert_xpath '//*[@id="header"]//*[@id="toc"]/*[@id="toctitle"][text()="Table of Contents"]', output, 1
1053
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol', output, 1
1054
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol[@type="none"][@class="sectlevel1"]', output, 1
1055
- assert_xpath '//*[@id="header"]//*[@id="toc"]//ol', output, 2
1056
- assert_xpath '//*[@id="header"]//*[@id="toc"]//ol[@type="none"]', output, 2
1057
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol/li', output, 4
1058
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol/li[1]/a[@href="#_section_one"][text()="Section One"]', output, 1
1059
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol/li/ol', output, 1
1060
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol/li/ol[@type="none"]', output, 1
1061
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol/li/ol[@class="sectlevel2"]', output, 1
1062
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol/li/ol/li', output, 1
1063
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol/li/ol/li/a[@href="#_interlude"][text()="Interlude"]', output, 1
1064
- assert_xpath '((//*[@id="header"]//*[@id="toc"]/ol)[1]/li)[4]/a[@href="#_section_three"][text()="Section Three"]', output, 1
1335
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul', output, 1
1336
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul[@class="sectlevel1"]', output, 1
1337
+ assert_xpath '//*[@id="header"]//*[@id="toc"]//ul', output, 2
1338
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li', output, 4
1339
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li[1]/a[@href="#_section_one"][text()="Section One"]', output, 1
1340
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li/ul', output, 1
1341
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li/ul[@class="sectlevel2"]', output, 1
1342
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li/ul/li', output, 1
1343
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li/ul/li/a[@href="#_interlude"][text()="Interlude"]', output, 1
1344
+ assert_xpath '((//*[@id="header"]//*[@id="toc"]/ul)[1]/li)[4]/a[@href="#_section_three"][text()="Section Three"]', output, 1
1065
1345
  end
1066
1346
 
1067
1347
  test 'should render numbered table of contents in header if toc and numbered attributes are set' do
@@ -1089,15 +1369,13 @@ That's all she wrote!
1089
1369
  output = render_string input
1090
1370
  assert_xpath '//*[@id="header"]//*[@id="toc"][@class="toc"]', output, 1
1091
1371
  assert_xpath '//*[@id="header"]//*[@id="toc"]/*[@id="toctitle"][text()="Table of Contents"]', output, 1
1092
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol', output, 1
1093
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol[@type="none"]', output, 1
1094
- assert_xpath '//*[@id="header"]//*[@id="toc"]//ol', output, 2
1095
- assert_xpath '//*[@id="header"]//*[@id="toc"]//ol[@type="none"]', output, 2
1096
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol/li', output, 4
1097
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol/li[1]/a[@href="#_section_one"][text()="1. Section One"]', output, 1
1098
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol/li/ol/li', output, 1
1099
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol/li/ol/li/a[@href="#_interlude"][text()="2.1. Interlude"]', output, 1
1100
- assert_xpath '((//*[@id="header"]//*[@id="toc"]/ol)[1]/li)[4]/a[@href="#_section_three"][text()="3. Section Three"]', output, 1
1372
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul', output, 1
1373
+ assert_xpath '//*[@id="header"]//*[@id="toc"]//ul', output, 2
1374
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li', output, 4
1375
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li[1]/a[@href="#_section_one"][text()="1. Section One"]', output, 1
1376
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li/ul/li', output, 1
1377
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li/ul/li/a[@href="#_interlude"][text()="2.1. Interlude"]', output, 1
1378
+ assert_xpath '((//*[@id="header"]//*[@id="toc"]/ul)[1]/li)[4]/a[@href="#_section_three"][text()="3. Section Three"]', output, 1
1101
1379
  end
1102
1380
 
1103
1381
  test 'should render a table of contents that honors numbered setting at position of section in document' do
@@ -1127,13 +1405,11 @@ That's all she wrote!
1127
1405
  output = render_string input
1128
1406
  assert_xpath '//*[@id="header"]//*[@id="toc"][@class="toc"]', output, 1
1129
1407
  assert_xpath '//*[@id="header"]//*[@id="toc"]/*[@id="toctitle"][text()="Table of Contents"]', output, 1
1130
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol', output, 1
1131
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol[@type="none"]', output, 1
1132
- assert_xpath '//*[@id="header"]//*[@id="toc"]//ol', output, 2
1133
- assert_xpath '//*[@id="header"]//*[@id="toc"]//ol[@type="none"]', output, 2
1134
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol/li', output, 4
1135
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol/li[1]/a[@href="#_section_one"][text()="1. Section One"]', output, 1
1136
- assert_xpath '((//*[@id="header"]//*[@id="toc"]/ol)[1]/li)[4]/a[@href="#_section_three"][text()="Section Three"]', output, 1
1408
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul', output, 1
1409
+ assert_xpath '//*[@id="header"]//*[@id="toc"]//ul', output, 2
1410
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li', output, 4
1411
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li[1]/a[@href="#_section_one"][text()="1. Section One"]', output, 1
1412
+ assert_xpath '((//*[@id="header"]//*[@id="toc"]/ul)[1]/li)[4]/a[@href="#_section_three"][text()="Section Three"]', output, 1
1137
1413
  end
1138
1414
 
1139
1415
  test 'should not number parts in table of contents for book doctype when numbered attribute is set' do
@@ -1162,15 +1438,15 @@ blah
1162
1438
 
1163
1439
  output = render_string input
1164
1440
  assert_xpath '//*[@id="toc"]', output, 1
1165
- assert_xpath '//*[@id="toc"]/ol', output, 1
1166
- assert_xpath '//*[@id="toc"]/ol[@type="none"][@class="sectlevel0"]', output, 1
1167
- assert_xpath '//*[@id="toc"]/ol[@type="none"][@class="sectlevel0"]/li', output, 4
1168
- assert_xpath '(//*[@id="toc"]/ol[@type="none"][@class="sectlevel0"]/li)[1]/a[text()="Part 1"]', output, 1
1169
- assert_xpath '(//*[@id="toc"]/ol[@type="none"][@class="sectlevel0"]/li)[3]/a[text()="Part 2"]', output, 1
1170
- assert_xpath '(//*[@id="toc"]/ol[@type="none"][@class="sectlevel0"]/li)[2]/ol', output, 1
1171
- assert_xpath '(//*[@id="toc"]/ol[@type="none"][@class="sectlevel0"]/li)[2]/ol[@type="none"][@class="sectlevel1"]', output, 1
1172
- assert_xpath '(//*[@id="toc"]/ol[@type="none"][@class="sectlevel0"]/li)[2]/ol/li', output, 2
1173
- assert_xpath '((//*[@id="toc"]/ol[@type="none"][@class="sectlevel0"]/li)[2]/ol/li)[1]/a[text()="1. First Section of Part 1"]', output, 1
1441
+ assert_xpath '//*[@id="toc"]/ul', output, 1
1442
+ assert_xpath '//*[@id="toc"]/ul[@class="sectlevel0"]', output, 1
1443
+ assert_xpath '//*[@id="toc"]/ul[@class="sectlevel0"]/li', output, 4
1444
+ assert_xpath '(//*[@id="toc"]/ul[@class="sectlevel0"]/li)[1]/a[text()="Part 1"]', output, 1
1445
+ assert_xpath '(//*[@id="toc"]/ul[@class="sectlevel0"]/li)[3]/a[text()="Part 2"]', output, 1
1446
+ assert_xpath '(//*[@id="toc"]/ul[@class="sectlevel0"]/li)[2]/ul', output, 1
1447
+ assert_xpath '(//*[@id="toc"]/ul[@class="sectlevel0"]/li)[2]/ul[@class="sectlevel1"]', output, 1
1448
+ assert_xpath '(//*[@id="toc"]/ul[@class="sectlevel0"]/li)[2]/ul/li', output, 2
1449
+ assert_xpath '((//*[@id="toc"]/ul[@class="sectlevel0"]/li)[2]/ul/li)[1]/a[text()="1. First Section of Part 1"]', output, 1
1174
1450
  end
1175
1451
 
1176
1452
  test 'should render table of contents in header if toc2 attribute is set' do
@@ -1189,9 +1465,95 @@ They couldn't believe their eyes when...
1189
1465
  EOS
1190
1466
 
1191
1467
  output = render_string input
1192
- assert_xpath '//body[@class="article toc2"]', output, 1
1468
+ assert_xpath '//body[@class="article toc2 toc-left"]', output, 1
1469
+ assert_xpath '//*[@id="header"]//*[@id="toc"][@class="toc2"]', output, 1
1470
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li[1]/a[@href="#_section_one"][text()="1. Section One"]', output, 1
1471
+ end
1472
+
1473
+ test 'should set toc position if toc2 attribute is set to position' do
1474
+ input = <<-EOS
1475
+ = Article
1476
+ :toc2: >
1477
+ :numbered:
1478
+
1479
+ == Section One
1480
+
1481
+ It was a dark and stormy night...
1482
+
1483
+ == Section Two
1484
+
1485
+ They couldn't believe their eyes when...
1486
+ EOS
1487
+
1488
+ output = render_string input
1489
+ assert_xpath '//body[@class="article toc2 toc-right"]', output, 1
1490
+ assert_xpath '//*[@id="header"]//*[@id="toc"][@class="toc2"]', output, 1
1491
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li[1]/a[@href="#_section_one"][text()="1. Section One"]', output, 1
1492
+ end
1493
+
1494
+ test 'should set toc position if toc and toc-position attributes are set' do
1495
+ input = <<-EOS
1496
+ = Article
1497
+ :toc:
1498
+ :toc-position: right
1499
+ :numbered:
1500
+
1501
+ == Section One
1502
+
1503
+ It was a dark and stormy night...
1504
+
1505
+ == Section Two
1506
+
1507
+ They couldn't believe their eyes when...
1508
+ EOS
1509
+
1510
+ output = render_string input
1511
+ assert_xpath '//body[@class="article toc2 toc-right"]', output, 1
1512
+ assert_xpath '//*[@id="header"]//*[@id="toc"][@class="toc2"]', output, 1
1513
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li[1]/a[@href="#_section_one"][text()="1. Section One"]', output, 1
1514
+ end
1515
+
1516
+ test 'should set toc position if toc2 and toc-position attribute are set' do
1517
+ input = <<-EOS
1518
+ = Article
1519
+ :toc2:
1520
+ :toc-position: right
1521
+ :numbered:
1522
+
1523
+ == Section One
1524
+
1525
+ It was a dark and stormy night...
1526
+
1527
+ == Section Two
1528
+
1529
+ They couldn't believe their eyes when...
1530
+ EOS
1531
+
1532
+ output = render_string input
1533
+ assert_xpath '//body[@class="article toc2 toc-right"]', output, 1
1534
+ assert_xpath '//*[@id="header"]//*[@id="toc"][@class="toc2"]', output, 1
1535
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li[1]/a[@href="#_section_one"][text()="1. Section One"]', output, 1
1536
+ end
1537
+
1538
+ test 'should set toc position if toc attribute is set to direction' do
1539
+ input = <<-EOS
1540
+ = Article
1541
+ :toc: right
1542
+ :numbered:
1543
+
1544
+ == Section One
1545
+
1546
+ It was a dark and stormy night...
1547
+
1548
+ == Section Two
1549
+
1550
+ They couldn't believe their eyes when...
1551
+ EOS
1552
+
1553
+ output = render_string input
1554
+ assert_xpath '//body[@class="article toc2 toc-right"]', output, 1
1193
1555
  assert_xpath '//*[@id="header"]//*[@id="toc"][@class="toc2"]', output, 1
1194
- assert_xpath '//*[@id="header"]//*[@id="toc"]/ol/li[1]/a[@href="#_section_one"][text()="1. Section One"]', output, 1
1556
+ assert_xpath '//*[@id="header"]//*[@id="toc"]/ul/li[1]/a[@href="#_section_one"][text()="1. Section One"]', output, 1
1195
1557
  end
1196
1558
 
1197
1559
  test 'should use document attributes toc-class, toc-title and toclevels to create toc' do
@@ -1224,27 +1586,6 @@ Fin.
1224
1586
  assert_xpath '//*[@id="header"]//*[@id="toc"]/*[@id="toctitle"][text()="Contents"]', output, 1
1225
1587
  end
1226
1588
 
1227
- test 'should render table of contents in preamble if toc-placement attribute value is preamble' do
1228
- input = <<-EOS
1229
- = Article
1230
- :toc:
1231
- :toc-placement: preamble
1232
-
1233
- Once upon a time...
1234
-
1235
- == Section One
1236
-
1237
- It was a dark and stormy night...
1238
-
1239
- == Section Two
1240
-
1241
- They couldn't believe their eyes when...
1242
- EOS
1243
-
1244
- output = render_string input
1245
- assert_xpath '//*[@id="preamble"]/*[@id="toc"]', output, 1
1246
- end
1247
-
1248
1589
  test 'should not render table of contents if toc-placement attribute is unset' do
1249
1590
  input = <<-EOS
1250
1591
  = Article