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.
- data/Gemfile +2 -0
- data/README.asciidoc +35 -26
- data/Rakefile +9 -6
- data/asciidoctor.gemspec +27 -8
- data/bin/asciidoctor +1 -1
- data/lib/asciidoctor.rb +351 -63
- data/lib/asciidoctor/abstract_block.rb +218 -0
- data/lib/asciidoctor/abstract_node.rb +249 -0
- data/lib/asciidoctor/attribute_list.rb +211 -0
- data/lib/asciidoctor/backends/base_template.rb +99 -0
- data/lib/asciidoctor/backends/docbook45.rb +510 -0
- data/lib/asciidoctor/backends/html5.rb +585 -0
- data/lib/asciidoctor/block.rb +27 -254
- data/lib/asciidoctor/callouts.rb +117 -0
- data/lib/asciidoctor/debug.rb +7 -4
- data/lib/asciidoctor/document.rb +229 -77
- data/lib/asciidoctor/inline.rb +29 -0
- data/lib/asciidoctor/lexer.rb +1330 -502
- data/lib/asciidoctor/list_item.rb +33 -34
- data/lib/asciidoctor/reader.rb +305 -142
- data/lib/asciidoctor/renderer.rb +115 -19
- data/lib/asciidoctor/section.rb +100 -189
- data/lib/asciidoctor/substituters.rb +468 -0
- data/lib/asciidoctor/table.rb +499 -0
- data/lib/asciidoctor/version.rb +1 -1
- data/test/attributes_test.rb +301 -87
- data/test/blocks_test.rb +568 -0
- data/test/document_test.rb +221 -24
- data/test/fixtures/dot.gif +0 -0
- data/test/fixtures/encoding.asciidoc +1 -0
- data/test/fixtures/include-file.asciidoc +1 -0
- data/test/fixtures/tip.gif +0 -0
- data/test/headers_test.rb +411 -43
- data/test/lexer_test.rb +265 -45
- data/test/links_test.rb +144 -3
- data/test/lists_test.rb +2252 -74
- data/test/paragraphs_test.rb +21 -30
- data/test/preamble_test.rb +24 -0
- data/test/reader_test.rb +248 -12
- data/test/renderer_test.rb +22 -0
- data/test/substitutions_test.rb +414 -0
- data/test/tables_test.rb +484 -0
- data/test/test_helper.rb +70 -6
- data/test/text_test.rb +30 -6
- metadata +64 -10
- data/lib/asciidoctor/render_templates.rb +0 -317
- data/lib/asciidoctor/string.rb +0 -12
data/test/document_test.rb
CHANGED
@@ -1,36 +1,233 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
data/test/headers_test.rb
CHANGED
@@ -1,47 +1,119 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
require 'test_helper'
|
2
3
|
|
3
|
-
context
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
40
|
-
|
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
|
-
|
44
|
-
|
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("
|
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("
|
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("
|
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
|