asciidoctor 0.0.7 → 0.0.9

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 (47) hide show
  1. data/Gemfile +2 -0
  2. data/README.asciidoc +35 -26
  3. data/Rakefile +9 -6
  4. data/asciidoctor.gemspec +27 -8
  5. data/bin/asciidoctor +1 -1
  6. data/lib/asciidoctor.rb +351 -63
  7. data/lib/asciidoctor/abstract_block.rb +218 -0
  8. data/lib/asciidoctor/abstract_node.rb +249 -0
  9. data/lib/asciidoctor/attribute_list.rb +211 -0
  10. data/lib/asciidoctor/backends/base_template.rb +99 -0
  11. data/lib/asciidoctor/backends/docbook45.rb +510 -0
  12. data/lib/asciidoctor/backends/html5.rb +585 -0
  13. data/lib/asciidoctor/block.rb +27 -254
  14. data/lib/asciidoctor/callouts.rb +117 -0
  15. data/lib/asciidoctor/debug.rb +7 -4
  16. data/lib/asciidoctor/document.rb +229 -77
  17. data/lib/asciidoctor/inline.rb +29 -0
  18. data/lib/asciidoctor/lexer.rb +1330 -502
  19. data/lib/asciidoctor/list_item.rb +33 -34
  20. data/lib/asciidoctor/reader.rb +305 -142
  21. data/lib/asciidoctor/renderer.rb +115 -19
  22. data/lib/asciidoctor/section.rb +100 -189
  23. data/lib/asciidoctor/substituters.rb +468 -0
  24. data/lib/asciidoctor/table.rb +499 -0
  25. data/lib/asciidoctor/version.rb +1 -1
  26. data/test/attributes_test.rb +301 -87
  27. data/test/blocks_test.rb +568 -0
  28. data/test/document_test.rb +221 -24
  29. data/test/fixtures/dot.gif +0 -0
  30. data/test/fixtures/encoding.asciidoc +1 -0
  31. data/test/fixtures/include-file.asciidoc +1 -0
  32. data/test/fixtures/tip.gif +0 -0
  33. data/test/headers_test.rb +411 -43
  34. data/test/lexer_test.rb +265 -45
  35. data/test/links_test.rb +144 -3
  36. data/test/lists_test.rb +2252 -74
  37. data/test/paragraphs_test.rb +21 -30
  38. data/test/preamble_test.rb +24 -0
  39. data/test/reader_test.rb +248 -12
  40. data/test/renderer_test.rb +22 -0
  41. data/test/substitutions_test.rb +414 -0
  42. data/test/tables_test.rb +484 -0
  43. data/test/test_helper.rb +70 -6
  44. data/test/text_test.rb +30 -6
  45. metadata +64 -10
  46. data/lib/asciidoctor/render_templates.rb +0 -317
  47. data/lib/asciidoctor/string.rb +0 -12
@@ -1,36 +1,233 @@
1
1
  require 'test_helper'
2
2
 
3
- class DocumentTest < Test::Unit::TestCase
4
- # setup for test
5
- def setup
6
- @doc = example_document(:asciidoc_index)
3
+ context 'Document' do
4
+
5
+ context 'Example document' do
6
+ test 'test_title' do
7
+ doc = example_document(:asciidoc_index)
8
+ assert_equal 'AsciiDoc Home Page', doc.doctitle
9
+ assert_equal 'AsciiDoc Home Page', doc.name
10
+ assert_equal 14, doc.blocks.size
11
+ assert_equal :preamble, doc.blocks[0].context
12
+ assert doc.blocks[1].is_a? ::Asciidoctor::Section
13
+ end
7
14
  end
8
15
 
9
- def test_title
10
- assert_equal "AsciiDoc Home Page", @doc.doctitle
11
- assert_equal 14, @doc.elements.size
12
- assert_equal :preamble, @doc.elements[0].context
13
- assert @doc.elements[1].is_a? ::Asciidoctor::Section
16
+ context 'Default settings' do
17
+ test 'safe mode level set to SECURE by default' do
18
+ doc = Asciidoctor::Document.new
19
+ assert_equal Asciidoctor::SafeMode::SECURE, doc.safe
20
+ end
21
+
22
+ test 'safe mode level can be set in the constructor' do
23
+ doc = Asciidoctor::Document.new [], :safe => Asciidoctor::SafeMode::SAFE
24
+ assert_equal Asciidoctor::SafeMode::SAFE, doc.safe
25
+ end
26
+
27
+ test 'safe model level cannot be modified' do
28
+ doc = Asciidoctor::Document.new
29
+ begin
30
+ doc.safe = Asciidoctor::SafeMode::UNSAFE
31
+ flunk 'safe mode property of Asciidoctor::Document should not be writable!'
32
+ rescue
33
+ end
34
+ end
14
35
  end
15
36
 
16
- def test_with_no_title
17
- d = Asciidoctor::Document.new(["Snorf"])
18
- assert_nil d.doctitle
37
+ context 'Renderer' do
38
+ test 'built-in HTML5 views are registered by default' do
39
+ doc = document_from_string ''
40
+ assert_equal 'html5', doc.attributes['backend']
41
+ assert doc.attributes.has_key? 'backend-html5'
42
+ assert_equal 'html', doc.attributes['basebackend']
43
+ assert doc.attributes.has_key? 'basebackend-html'
44
+ renderer = doc.renderer
45
+ assert !renderer.nil?
46
+ views = renderer.views
47
+ assert !views.nil?
48
+ assert_equal 26, views.size
49
+ assert views.has_key? 'document'
50
+ assert views['document'].is_a?(Asciidoctor::HTML5::DocumentTemplate)
51
+ assert_equal 'ERB', views['document'].eruby.to_s
52
+ end
53
+
54
+ test 'built-in DocBook45 views are registered when backend is docbook45' do
55
+ doc = document_from_string '', :attributes => {'backend' => 'docbook45'}
56
+ renderer = doc.renderer
57
+ assert_equal 'docbook45', doc.attributes['backend']
58
+ assert doc.attributes.has_key? 'backend-docbook45'
59
+ assert_equal 'docbook', doc.attributes['basebackend']
60
+ assert doc.attributes.has_key? 'basebackend-docbook'
61
+ assert !renderer.nil?
62
+ views = renderer.views
63
+ assert !views.nil?
64
+ assert_equal 26, views.size
65
+ assert views.has_key? 'document'
66
+ assert views['document'].is_a?(Asciidoctor::DocBook45::DocumentTemplate)
67
+ assert_equal 'ERB', views['document'].eruby.to_s
68
+ end
69
+
70
+ test 'can set erubis as eRuby implementation' do
71
+ doc = Asciidoctor::Document.new [], :eruby => 'erubis'
72
+ assert $LOADED_FEATURES.detect {|p| p == 'erubis.rb' || p.end_with?('/erubis.rb') }.nil?
73
+ renderer = doc.renderer
74
+ assert $LOADED_FEATURES.detect {|p| p == 'erubis.rb' || p.end_with?('/erubis.rb') }
75
+ views = renderer.views
76
+ assert !views.nil?
77
+ assert views.has_key? 'document'
78
+ assert_equal 'Erubis::FastEruby', views['document'].eruby.to_s
79
+ assert_equal 'Erubis::FastEruby', views['document'].template.class.to_s
80
+ end
19
81
  end
20
82
 
21
- def test_with_header_footer
22
- result = render_string("= Title\n\npreamble")
23
- assert_xpath '/html', result, 1
24
- assert_xpath '//*[@id="header"]', result, 1
25
- assert_xpath '//*[@id="footer"]', result, 1
26
- assert_xpath '//*[@id="preamble"]', result, 1
83
+ context 'Structure' do
84
+ test 'test_with_no_title' do
85
+ doc = document_from_string('Snorf')
86
+ assert_nil doc.doctitle
87
+ assert_nil doc.name
88
+ assert !doc.has_header?
89
+ assert_nil doc.header
90
+ end
91
+
92
+ test 'test_with_explicit_title' do
93
+ input = <<-EOS
94
+ = Title
95
+ :title: Document Title
96
+
97
+ preamble
98
+
99
+ == First Section
100
+ EOS
101
+ doc = document_from_string input
102
+ assert_equal 'Document Title', doc.doctitle
103
+ assert_equal 'Document Title', doc.title
104
+ assert doc.has_header?
105
+ assert_equal 'Title', doc.header.title
106
+ assert_equal 'Title', doc.first_section.title
107
+ end
108
+
109
+ test 'test_empty_document' do
110
+ doc = document_from_string('')
111
+ assert doc.blocks.empty?
112
+ assert_nil doc.doctitle
113
+ assert !doc.has_header?
114
+ assert_nil doc.header
115
+ end
116
+
117
+ test 'test_with_metadata' do
118
+ input = <<-EOS
119
+ = AsciiDoc
120
+ Stuart Rackham <founder@asciidoc.org>
121
+ v8.6.8, 2012-07-12: See changelog.
122
+
123
+ == Version 8.6.8
124
+
125
+ more info...
126
+ EOS
127
+ output = render_string input
128
+ assert_xpath '//*[@id="header"]/span[@id="author"][text() = "Stuart Rackham"]', output, 1
129
+ assert_xpath '//*[@id="header"]/span[@id="email"][contains(text(), "founder@asciidoc.org")]', output, 1
130
+ assert_xpath '//*[@id="header"]/span[@id="revnumber"][text() = "version 8.6.8,"]', output, 1
131
+ assert_xpath '//*[@id="header"]/span[@id="revdate"][text() = "2012-07-12"]', output, 1
132
+ assert_xpath '//*[@id="header"]/span[@id="revremark"][text() = "See changelog."]', output, 1
133
+ end
134
+
135
+ test 'test_with_header_footer' do
136
+ result = render_string("= Title\n\npreamble")
137
+ assert_xpath '/html', result, 1
138
+ assert_xpath '//*[@id="header"]', result, 1
139
+ assert_xpath '//*[@id="footer"]', result, 1
140
+ assert_xpath '//*[@id="preamble"]', result, 1
141
+ end
142
+
143
+ test 'test_with_no_header_footer' do
144
+ result = render_string("= Title\n\npreamble", :header_footer => false)
145
+ assert_xpath '/html', result, 0
146
+ assert_xpath '/*[@id="header"]', result, 0
147
+ assert_xpath '/*[@id="footer"]', result, 0
148
+ assert_xpath '/*[@id="preamble"]', result, 1
149
+ end
27
150
  end
28
151
 
29
- def test_with_no_header_footer
30
- result = render_string("= Title\n\npreamble", :header_footer => false)
31
- assert_xpath '/html', result, 0
32
- assert_xpath '/*[@id="header"]', result, 0
33
- assert_xpath '/*[@id="footer"]', result, 0
34
- assert_xpath '/*[@id="preamble"]', result, 1
152
+ context 'Backends and Doctypes' do
153
+ test 'test_html5_backend_doctype_article' do
154
+ result = render_string("= Title\n\npreamble", :attributes => {'backend' => 'html5'})
155
+ assert_xpath '/html', result, 1
156
+ assert_xpath '/html/body[@class="article"]', result, 1
157
+ assert_xpath '/html//*[@id="header"]/h1[text() = "Title"]', result, 1
158
+ assert_xpath '/html//*[@id="preamble"]//p[text() = "preamble"]', result, 1
159
+ end
160
+
161
+ test 'test_html5_backend_doctype_book' do
162
+ result = render_string("= Title\n\npreamble", :attributes => {'backend' => 'html5', 'doctype' => 'book'})
163
+ assert_xpath '/html', result, 1
164
+ assert_xpath '/html/body[@class="book"]', result, 1
165
+ assert_xpath '/html//*[@id="header"]/h1[text() = "Title"]', result, 1
166
+ assert_xpath '/html//*[@id="preamble"]//p[text() = "preamble"]', result, 1
167
+ end
168
+
169
+ test 'test_docbook45_backend_doctype_article' do
170
+ input = <<-EOS
171
+ = Title
172
+
173
+ preamble
174
+
175
+ == First Section
176
+
177
+ section body
178
+ EOS
179
+ result = render_string(input, :attributes => {'backend' => 'docbook45'})
180
+ assert_xpath '/article', result, 1
181
+ assert_xpath '/article/articleinfo/title[text() = "Title"]', result, 1
182
+ assert_xpath '/article/simpara[text() = "preamble"]', result, 1
183
+ assert_xpath '/article/section', result, 1
184
+ assert_xpath '/article/section[@id = "_first_section"]/title[text() = "First Section"]', result, 1
185
+ assert_xpath '/article/section[@id = "_first_section"]/simpara[text() = "section body"]', result, 1
186
+ end
187
+
188
+ test 'test_docbook45_backend_doctype_article_no_title' do
189
+ result = render_string('text', :attributes => {'backend' => 'docbook45'})
190
+ assert_xpath '/article', result, 1
191
+ assert_xpath '/article/articleinfo/date', result, 1
192
+ assert_xpath '/article/simpara[text() = "text"]', result, 1
193
+ end
194
+
195
+ test 'test_docbook45_backend_doctype_book' do
196
+ input = <<-EOS
197
+ = Title
198
+
199
+ preamble
200
+
201
+ == First Chapter
202
+
203
+ chapter body
204
+ EOS
205
+ result = render_string(input, :attributes => {'backend' => 'docbook45', 'doctype' => 'book'})
206
+ assert_xpath '/book', result, 1
207
+ assert_xpath '/book/bookinfo/title[text() = "Title"]', result, 1
208
+ assert_xpath '/book/preface/simpara[text() = "preamble"]', result, 1
209
+ assert_xpath '/book/chapter', result, 1
210
+ assert_xpath '/book/chapter[@id = "_first_chapter"]/title[text() = "First Chapter"]', result, 1
211
+ assert_xpath '/book/chapter[@id = "_first_chapter"]/simpara[text() = "chapter body"]', result, 1
212
+ end
213
+
214
+ test 'test_docbook45_backend_doctype_book_no_title' do
215
+ result = render_string('text', :attributes => {'backend' => 'docbook45', 'doctype' => 'book'})
216
+ assert_xpath '/book', result, 1
217
+ assert_xpath '/book/bookinfo/date', result, 1
218
+ assert_xpath '/book/simpara[text() = "text"]', result, 1
219
+ end
220
+
221
+ test 'do not override explicit author initials' do
222
+ input = <<-EOS
223
+ = AsciiDoc
224
+ Stuart Rackham <founder@asciidoc.org>
225
+ :Author Initials: SJR
226
+
227
+ more info...
228
+ EOS
229
+ output = render_string input, :attributes => {'backend' => 'docbook45'}
230
+ assert_xpath '/article/articleinfo/authorinitials[text()="SJR"]', output, 1
231
+ end
35
232
  end
36
233
  end
Binary file
@@ -0,0 +1 @@
1
+ Gregory Romé has written an AsciiDoc plugin for the Redmine project management application.
@@ -0,0 +1 @@
1
+ included content
Binary file
@@ -1,47 +1,119 @@
1
+ # encoding: UTF-8
1
2
  require 'test_helper'
2
3
 
3
- context "Headers" do
4
- test "document title with multiline syntax" do
5
- title = "My Title"
6
- chars = "=" * title.length
7
- assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string(title + "\n" + chars)
8
- assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string(title + "\n" + chars + "\n")
9
- end
4
+ context 'Sections' do
5
+ context 'Ids' do
6
+ test 'synthetic id is generated by default' do
7
+ sec = block_from_string('== Section One')
8
+ assert_equal '_section_one', sec.id
9
+ end
10
10
 
11
- test "document title with multiline syntax, give a char" do
12
- title = "My Title"
13
- chars = "=" * (title.length + 1)
14
- assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string(title + "\n" + chars)
15
- assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string(title + "\n" + chars + "\n")
16
- end
11
+ test 'synthetic id replaces non-word characters with underscores' do
12
+ sec = block_from_string("== We're back!")
13
+ assert_equal '_we_re_back', sec.id
14
+ end
17
15
 
18
- test "document title with multiline syntax, take a char" do
19
- title = "My Title"
20
- chars = "=" * (title.length - 1)
21
- assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string(title + "\n" + chars)
22
- assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string(title + "\n" + chars + "\n")
23
- end
16
+ test 'synthetic id removes repeating underscores' do
17
+ sec = block_from_string('== Section $ One')
18
+ assert_equal '_section_one', sec.id
19
+ end
24
20
 
25
- test "not enough chars for a multiline document title" do
26
- title = "My Title"
27
- chars = "=" * (title.length - 2)
28
- assert_xpath '//h1', render_string(title + "\n" + chars), 0
29
- assert_xpath '//h1', render_string(title + "\n" + chars + "\n"), 0
30
- end
21
+ test 'synthetic id prefix can be customized' do
22
+ sec = block_from_string(":idprefix: id_\n\n== Section One")
23
+ assert_equal 'id_section_one', sec.id
24
+ end
31
25
 
32
- test "too many chars for a multiline document title" do
33
- title = "My Title"
34
- chars = "=" * (title.length + 2)
35
- assert_xpath '//h1', render_string(title + "\n" + chars), 0
36
- assert_xpath '//h1', render_string(title + "\n" + chars + "\n"), 0
37
- end
26
+ test 'synthetic id prefix can be set to blank' do
27
+ sec = block_from_string(":idprefix:\n\n== Section One")
28
+ assert_equal 'section_one', sec.id
29
+ end
30
+
31
+ test 'synthetic ids can be disabled' do
32
+ sec = block_from_string(":sectids!:\n\n== Section One\n")
33
+ assert sec.id.nil?
34
+ end
35
+
36
+ test 'explicit id in anchor above section title overrides synthetic id' do
37
+ sec = block_from_string("[[one]]\n== Section One")
38
+ assert_equal 'one', sec.id
39
+ end
40
+
41
+ test 'explicit id can be defined using an inline anchor' do
42
+ sec = block_from_string("== Section One [[one]] ==")
43
+ assert_equal 'one', sec.id
44
+ assert_equal 'Section One', sec.title
45
+ end
38
46
 
39
- test "document title with single-line syntax" do
40
- assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string("= My Title")
47
+ test 'title substitutions are applied before generating id' do
48
+ sec = block_from_string("== Section{sp}One\n")
49
+ assert_equal '_section_one', sec.id
50
+ end
51
+
52
+ test 'synthetic ids are unique' do
53
+ input = <<-EOS
54
+ == Some section
55
+
56
+ text
57
+
58
+ == Some section
59
+
60
+ text
61
+ EOS
62
+ doc = document_from_string input
63
+ assert_equal '_some_section', doc.blocks[0].id
64
+ assert_equal '_some_section_2', doc.blocks[1].id
65
+ end
41
66
  end
42
67
 
43
- test "document title with symmetric syntax" do
44
- assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string("= My Title =")
68
+ context "document title (level 0)" do
69
+ test "document title with multiline syntax" do
70
+ title = "My Title"
71
+ chars = "=" * title.length
72
+ assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string(title + "\n" + chars)
73
+ assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string(title + "\n" + chars + "\n")
74
+ end
75
+
76
+ test "document title with multiline syntax, give a char" do
77
+ title = "My Title"
78
+ chars = "=" * (title.length + 1)
79
+ assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string(title + "\n" + chars)
80
+ assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string(title + "\n" + chars + "\n")
81
+ end
82
+
83
+ test "document title with multiline syntax, take a char" do
84
+ title = "My Title"
85
+ chars = "=" * (title.length - 1)
86
+ assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string(title + "\n" + chars)
87
+ assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string(title + "\n" + chars + "\n")
88
+ end
89
+
90
+ test "not enough chars for a multiline document title" do
91
+ title = "My Title"
92
+ chars = "=" * (title.length - 2)
93
+ assert_xpath '//h1', render_string(title + "\n" + chars), 0
94
+ assert_xpath '//h1', render_string(title + "\n" + chars + "\n"), 0
95
+ end
96
+
97
+ test "too many chars for a multiline document title" do
98
+ title = "My Title"
99
+ chars = "=" * (title.length + 2)
100
+ assert_xpath '//h1', render_string(title + "\n" + chars), 0
101
+ assert_xpath '//h1', render_string(title + "\n" + chars + "\n"), 0
102
+ end
103
+
104
+ test "document title with multiline syntax cannot begin with a dot" do
105
+ title = ".My Title"
106
+ chars = "=" * title.length
107
+ assert_xpath '//h1', render_string(title + "\n" + chars), 0
108
+ end
109
+
110
+ test "document title with single-line syntax" do
111
+ assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string("= My Title")
112
+ end
113
+
114
+ test "document title with symmetric syntax" do
115
+ assert_xpath "//h1[not(@id)][text() = 'My Title']", render_string("= My Title =")
116
+ end
45
117
  end
46
118
 
47
119
  context "level 1" do
@@ -49,6 +121,12 @@ context "Headers" do
49
121
  assert_xpath "//h2[@id='_my_section'][text() = 'My Section']", render_string("My Section\n-----------")
50
122
  end
51
123
 
124
+ test "heading title with multiline syntax cannot begin with a dot" do
125
+ title = ".My Title"
126
+ chars = "-" * title.length
127
+ assert_xpath '//h2', render_string(title + "\n" + chars), 0
128
+ end
129
+
52
130
  test "with single-line syntax" do
53
131
  assert_xpath "//h2[@id='_my_title'][text() = 'My Title']", render_string("== My Title")
54
132
  end
@@ -62,7 +140,7 @@ context "Headers" do
62
140
  end
63
141
 
64
142
  test "with non-word character" do
65
- assert_xpath "//h2[@id='_where_s_the_love'][text() = \"Where's the love?\"]", render_string("== Where's the love?")
143
+ assert_xpath "//h2[@id='_where_s_the_love'][text() = \"Where#{[8217].pack('U*')}s the love?\"]", render_string("== Where's the love?")
66
144
  end
67
145
 
68
146
  test "with sequential non-word characters" do
@@ -80,35 +158,325 @@ context "Headers" do
80
158
  test "with custom non-blank idprefix" do
81
159
  assert_xpath "//h2[@id='ref_my_title'][text() = 'My Title']", render_string(":idprefix: ref_\n\n== My Title ")
82
160
  end
161
+
162
+ test 'with multibyte characters' do
163
+ input = <<-EOS
164
+ == Asciidoctor in 中文
165
+ EOS
166
+ output = render_string input
167
+ assert_xpath '//h2[@id="_asciidoctor_in"][text()="Asciidoctor in 中文"]', output
168
+ end
83
169
  end
84
170
 
85
171
  context "level 2" do
86
172
  test "with multiline syntax" do
87
- assert_xpath "//h3[@id='_my_section'][text() = 'My Section']", render_string("My Section\n~~~~~~~~~~~")
173
+ assert_xpath "//h3[@id='_my_section'][text() = 'My Section']", render_string(":fragment:\nMy Section\n~~~~~~~~~~~")
88
174
  end
89
175
 
90
176
  test "with single line syntax" do
91
- assert_xpath "//h3[@id='_my_title'][text() = 'My Title']", render_string("=== My Title")
177
+ assert_xpath "//h3[@id='_my_title'][text() = 'My Title']", render_string(":fragment:\n=== My Title")
92
178
  end
93
179
  end
94
180
 
95
181
  context "level 3" do
96
182
  test "with multiline syntax" do
97
- assert_xpath "//h4[@id='_my_section'][text() = 'My Section']", render_string("My Section\n^^^^^^^^^^")
183
+ assert_xpath "//h4[@id='_my_section'][text() = 'My Section']", render_string(":fragment:\nMy Section\n^^^^^^^^^^")
98
184
  end
99
185
 
100
186
  test "with single line syntax" do
101
- assert_xpath "//h4[@id='_my_title'][text() = 'My Title']", render_string("==== My Title")
187
+ assert_xpath "//h4[@id='_my_title'][text() = 'My Title']", render_string(":fragment:\n==== My Title")
102
188
  end
103
189
  end
104
190
 
105
191
  context "level 4" do
106
192
  test "with multiline syntax" do
107
- assert_xpath "//h5[@id='_my_section'][text() = 'My Section']", render_string("My Section\n++++++++++")
193
+ assert_xpath "//h5[@id='_my_section'][text() = 'My Section']", render_string(":fragment:\nMy Section\n++++++++++")
108
194
  end
109
195
 
110
196
  test "with single line syntax" do
111
- assert_xpath "//h5[@id='_my_title'][text() = 'My Title']", render_string("===== My Title")
197
+ assert_xpath "//h5[@id='_my_title'][text() = 'My Title']", render_string(":fragment:\n===== My Title")
112
198
  end
113
- end
199
+ end
200
+
201
+ context 'Section Numbering' do
202
+ test 'should create section number with one entry for level 1' do
203
+ sect1 = Asciidoctor::Section.new(nil)
204
+ sect1.level = 1
205
+ assert_equal '1.', sect1.sectnum
206
+ end
207
+
208
+ test 'should create section number with two entries for level 2' do
209
+ sect1 = Asciidoctor::Section.new(nil)
210
+ sect1.level = 1
211
+ sect1_1 = Asciidoctor::Section.new(sect1)
212
+ sect1 << sect1_1
213
+ assert_equal '1.1.', sect1_1.sectnum
214
+ end
215
+
216
+ test 'should create section number with three entries for level 3' do
217
+ sect1 = Asciidoctor::Section.new(nil)
218
+ sect1.level = 1
219
+ sect1_1 = Asciidoctor::Section.new(sect1)
220
+ sect1 << sect1_1
221
+ sect1_1_1 = Asciidoctor::Section.new(sect1_1)
222
+ sect1_1 << sect1_1_1
223
+ assert_equal '1.1.1.', sect1_1_1.sectnum
224
+ end
225
+
226
+ test 'should create section number for second section in level' do
227
+ sect1 = Asciidoctor::Section.new(nil)
228
+ sect1.level = 1
229
+ sect1_1 = Asciidoctor::Section.new(sect1)
230
+ sect1 << sect1_1
231
+ sect1_2 = Asciidoctor::Section.new(sect1)
232
+ sect1 << sect1_2
233
+ assert_equal '1.2.', sect1_2.sectnum
234
+ end
235
+
236
+ test 'sectnum should use specified delimiter and append string' do
237
+ sect1 = Asciidoctor::Section.new(nil)
238
+ sect1.level = 1
239
+ sect1_1 = Asciidoctor::Section.new(sect1)
240
+ sect1 << sect1_1
241
+ sect1_1_1 = Asciidoctor::Section.new(sect1_1)
242
+ sect1_1 << sect1_1_1
243
+ assert_equal '1,1,1,', sect1_1_1.sectnum(',')
244
+ assert_equal '1:1:1', sect1_1_1.sectnum(':', false)
245
+ end
246
+
247
+ test 'should render section numbers when numbered attribute is set' do
248
+ input = <<-EOS
249
+ = Title
250
+ :numbered:
251
+
252
+ == Section_1
253
+
254
+ text
255
+
256
+ === Section_1_1
257
+
258
+ text
259
+
260
+ ==== Section_1_1_1
261
+
262
+ text
263
+
264
+ == Section_2
265
+
266
+ text
267
+
268
+ === Section_2_1
269
+
270
+ text
271
+
272
+ === Section_2_2
273
+
274
+ text
275
+ EOS
276
+
277
+ output = render_string input
278
+ assert_xpath '//h2[@id="_section_1"][starts-with(text(), "1. ")]', output, 1
279
+ assert_xpath '//h3[@id="_section_1_1"][starts-with(text(), "1.1. ")]', output, 1
280
+ assert_xpath '//h4[@id="_section_1_1_1"][starts-with(text(), "1.1.1. ")]', output, 1
281
+ assert_xpath '//h2[@id="_section_2"][starts-with(text(), "2. ")]', output, 1
282
+ assert_xpath '//h3[@id="_section_2_1"][starts-with(text(), "2.1. ")]', output, 1
283
+ assert_xpath '//h3[@id="_section_2_2"][starts-with(text(), "2.2. ")]', output, 1
284
+ end
285
+
286
+ test 'blocks should have level' do
287
+ input = <<-EOS
288
+ = Title
289
+
290
+ preamble
291
+
292
+ == Section 1
293
+
294
+ paragraph
295
+
296
+ === Section 1.1
297
+
298
+ paragraph
299
+ EOS
300
+ doc = document_from_string input
301
+ assert_equal 0, doc.blocks[0].level
302
+ assert_equal 1, doc.blocks[1].level
303
+ assert_equal 1, doc.blocks[1].blocks[0].level
304
+ assert_equal 2, doc.blocks[1].blocks[1].level
305
+ assert_equal 2, doc.blocks[1].blocks[1].blocks[0].level
306
+ end
307
+ end
308
+
309
+ context "heading patterns in blocks" do
310
+ test "should not interpret a listing block as a heading" do
311
+ input = <<-EOS
312
+ Section
313
+ -------
314
+
315
+ ----
316
+ code
317
+ ----
318
+
319
+ fin.
320
+ EOS
321
+ output = render_string input
322
+ assert_xpath "//h2", output, 1
323
+ end
324
+
325
+ test "should not interpret an open block as a heading" do
326
+ input = <<-EOS
327
+ Section
328
+ -------
329
+
330
+ --
331
+ ha
332
+ --
333
+
334
+ fin.
335
+ EOS
336
+ output = render_string input
337
+ assert_xpath "//h2", output, 1
338
+ end
339
+
340
+ test "should not interpret an attribute list as a heading" do
341
+ input = <<-EOS
342
+ Section
343
+ =======
344
+
345
+ preamble
346
+
347
+ [TIP]
348
+ ====
349
+ This should be a tip, not a heading.
350
+ ====
351
+ EOS
352
+ output = render_string input
353
+ assert_xpath "//*[@class='admonitionblock']//p[text() = 'This should be a tip, not a heading.']", output, 1
354
+ end
355
+
356
+ test "should not match a heading in a labeled list" do
357
+ input = <<-EOS
358
+ Section
359
+ -------
360
+
361
+ term1::
362
+ +
363
+ ----
364
+ list = [1, 2, 3];
365
+ ----
366
+ term2::
367
+ == not a heading
368
+ term3:: def
369
+
370
+ //
371
+
372
+ fin.
373
+ EOS
374
+ output = render_string input
375
+ assert_xpath "//h2", output, 1
376
+ assert_xpath "//dl", output, 1
377
+ end
378
+
379
+ test "should not match a heading in a bulleted list" do
380
+ input = <<-EOS
381
+ Section
382
+ -------
383
+
384
+ * first
385
+ +
386
+ ----
387
+ list = [1, 2, 3];
388
+ ----
389
+ +
390
+ * second
391
+ == not a heading
392
+ * third
393
+
394
+ fin.
395
+ EOS
396
+ output = render_string input
397
+ assert_xpath "//h2", output, 1
398
+ assert_xpath "//ul", output, 1
399
+ end
400
+
401
+ test "should not match a heading in a block" do
402
+ input = <<-EOS
403
+ ====
404
+
405
+ == not a heading
406
+
407
+ ====
408
+ EOS
409
+ output = render_string input
410
+ assert_xpath "//h2", output, 0
411
+ assert_xpath "//*[@class='exampleblock']//p[text() = '== not a heading']", output, 1
412
+ end
413
+ end
414
+
415
+ context 'Table of Contents' do
416
+ test 'should render table of contents if toc attribute is set' do
417
+ input = <<-EOS
418
+ Article
419
+ =======
420
+ :toc:
421
+
422
+ == Section One
423
+
424
+ It was a dark and stormy night...
425
+
426
+ == Section Two
427
+
428
+ They couldn't believe their eyes when...
429
+
430
+ === Interlude
431
+
432
+ While they were waiting...
433
+
434
+ == Section Three
435
+
436
+ That's all she wrote!
437
+ EOS
438
+ output = render_string input
439
+ assert_xpath '//*[@id="toc"]', output, 1
440
+ assert_xpath '//*[@id="toc"]/*[@id="toctitle"][text()="Table of Contents"]', output, 1
441
+ assert_xpath '//*[@id="toc"]/ol', output, 1
442
+ assert_xpath '//*[@id="toc"]//ol', output, 2
443
+ assert_xpath '//*[@id="toc"]/ol/li', output, 4
444
+ assert_xpath '//*[@id="toc"]/ol/li[1]/a[@href="#_section_one"][text()="1. Section One"]', output, 1
445
+ assert_xpath '//*[@id="toc"]/ol/li/ol/li', output, 1
446
+ assert_xpath '//*[@id="toc"]/ol/li/ol/li/a[@href="#_interlude"][text()="2.1. Interlude"]', output, 1
447
+ end
448
+ end
449
+
450
+ context "book doctype" do
451
+ test "document title with level 0 headings" do
452
+ input = <<-EOS
453
+ Book
454
+ ====
455
+ :doctype: book
456
+
457
+ = Chapter One
458
+
459
+ It was a dark and stormy night...
460
+
461
+ = Chapter Two
462
+
463
+ They couldn't believe their eyes when...
464
+
465
+ == Interlude
466
+
467
+ While they were waiting...
468
+
469
+ = Chapter Three
470
+
471
+ That's all she wrote!
472
+ EOS
473
+
474
+ output = render_string(input)
475
+ assert_xpath '//h1', output, 4
476
+ assert_xpath '//h2', output, 1
477
+ assert_xpath '//h1[@id="_chapter_one"][text() = "Chapter One"]', output, 1
478
+ assert_xpath '//h1[@id="_chapter_two"][text() = "Chapter Two"]', output, 1
479
+ assert_xpath '//h1[@id="_chapter_three"][text() = "Chapter Three"]', output, 1
480
+ end
481
+ end
114
482
  end