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.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +387 -0
- data/README.adoc +358 -348
- data/asciidoctor.gemspec +30 -9
- data/bin/asciidoctor +3 -0
- data/bin/asciidoctor-safe +3 -0
- data/compat/asciidoc.conf +76 -4
- data/lib/asciidoctor.rb +174 -79
- data/lib/asciidoctor/abstract_block.rb +131 -101
- data/lib/asciidoctor/abstract_node.rb +108 -26
- data/lib/asciidoctor/attribute_list.rb +1 -1
- data/lib/asciidoctor/backends/_stylesheets.rb +204 -62
- data/lib/asciidoctor/backends/base_template.rb +11 -22
- data/lib/asciidoctor/backends/docbook45.rb +158 -163
- data/lib/asciidoctor/backends/docbook5.rb +103 -0
- data/lib/asciidoctor/backends/html5.rb +662 -445
- data/lib/asciidoctor/block.rb +54 -44
- data/lib/asciidoctor/cli/invoker.rb +41 -20
- data/lib/asciidoctor/cli/options.rb +66 -20
- data/lib/asciidoctor/debug.rb +1 -1
- data/lib/asciidoctor/document.rb +265 -100
- data/lib/asciidoctor/extensions.rb +443 -0
- data/lib/asciidoctor/helpers.rb +38 -6
- data/lib/asciidoctor/inline.rb +5 -5
- data/lib/asciidoctor/lexer.rb +532 -250
- data/lib/asciidoctor/{list_item.rb → list.rb} +33 -13
- data/lib/asciidoctor/path_resolver.rb +28 -2
- data/lib/asciidoctor/reader.rb +814 -455
- data/lib/asciidoctor/renderer.rb +128 -42
- data/lib/asciidoctor/section.rb +55 -41
- data/lib/asciidoctor/substituters.rb +380 -107
- data/lib/asciidoctor/table.rb +40 -30
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +32 -96
- data/man/{asciidoctor.ad → asciidoctor.adoc} +57 -48
- data/test/attributes_test.rb +200 -27
- data/test/blocks_test.rb +361 -22
- data/test/document_test.rb +496 -81
- data/test/extensions_test.rb +448 -0
- data/test/fixtures/basic-docinfo-footer.html +6 -0
- data/test/fixtures/basic-docinfo-footer.xml +8 -0
- data/test/fixtures/basic-docinfo.xml +3 -3
- data/test/fixtures/basic.asciidoc +1 -0
- data/test/fixtures/child-include.adoc +5 -0
- data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +6 -0
- data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +1 -0
- data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +3 -0
- data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +5 -0
- data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +6 -0
- data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +3 -0
- data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +5 -0
- data/test/fixtures/docinfo-footer.html +1 -0
- data/test/fixtures/docinfo-footer.xml +9 -0
- data/test/fixtures/docinfo.xml +1 -0
- data/test/fixtures/grandchild-include.adoc +3 -0
- data/test/fixtures/parent-include-restricted.adoc +5 -0
- data/test/fixtures/parent-include.adoc +5 -0
- data/test/invoker_test.rb +82 -8
- data/test/lexer_test.rb +21 -3
- data/test/links_test.rb +34 -2
- data/test/lists_test.rb +304 -7
- data/test/options_test.rb +19 -3
- data/test/paragraphs_test.rb +13 -0
- data/test/paths_test.rb +22 -0
- data/test/preamble_test.rb +20 -0
- data/test/reader_test.rb +1096 -644
- data/test/renderer_test.rb +152 -12
- data/test/sections_test.rb +417 -76
- data/test/substitutions_test.rb +339 -138
- data/test/tables_test.rb +109 -4
- data/test/test_helper.rb +79 -13
- data/test/text_test.rb +111 -11
- metadata +54 -18
@@ -1,4 +1,4 @@
|
|
1
|
-
<copyright
|
2
|
-
|
3
|
-
|
1
|
+
<copyright><!-- don't remove the indent! -->
|
2
|
+
<year>2013</year>
|
3
|
+
<holder>Acme, Inc.</holder>
|
4
4
|
</copyright>
|
@@ -0,0 +1 @@
|
|
1
|
+
%p=content
|
@@ -0,0 +1 @@
|
|
1
|
+
<a id="top" href="#">Back to top</a>
|
data/test/fixtures/docinfo.xml
CHANGED
data/test/invoker_test.rb
CHANGED
@@ -58,6 +58,25 @@ context 'Invoker' do
|
|
58
58
|
assert_xpath '/*[@class="paragraph"]/p[text()="content"]', output, 1
|
59
59
|
end
|
60
60
|
|
61
|
+
test 'should accept document from stdin and write to output file' do
|
62
|
+
sample_outpath = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'sample-output.html'))
|
63
|
+
begin
|
64
|
+
invoker = invoke_cli(%W(-s -o #{sample_outpath}), '-') { 'content' }
|
65
|
+
doc = invoker.document
|
66
|
+
assert !doc.attr?('docname')
|
67
|
+
assert !doc.attr?('docfile')
|
68
|
+
assert_equal Dir.pwd, doc.attr('docdir')
|
69
|
+
assert_equal doc.attr('docdate'), doc.attr('localdate')
|
70
|
+
assert_equal doc.attr('doctime'), doc.attr('localtime')
|
71
|
+
assert_equal doc.attr('docdatetime'), doc.attr('localdatetime')
|
72
|
+
assert doc.attr?('outfile')
|
73
|
+
assert_equal sample_outpath, doc.attr('outfile')
|
74
|
+
assert File.exist?(sample_outpath)
|
75
|
+
ensure
|
76
|
+
FileUtils::rm_f(sample_outpath)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
61
80
|
test 'should allow docdir to be specified when input is a string' do
|
62
81
|
expected_docdir = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures'))
|
63
82
|
invoker = invoke_cli_to_buffer(%w(-s --base-dir test/fixtures -o /dev/null), '-') { 'content' }
|
@@ -88,10 +107,10 @@ context 'Invoker' do
|
|
88
107
|
end
|
89
108
|
end
|
90
109
|
|
91
|
-
test 'should
|
110
|
+
test 'should treat extra arguments as files' do
|
92
111
|
redirect_streams do |stdout, stderr|
|
93
112
|
invoker = invoke_cli %w(-o /dev/null extra arguments sample.asciidoc), nil
|
94
|
-
assert_match(/
|
113
|
+
assert_match(/input file .* missing/, stderr.string)
|
95
114
|
assert_equal 1, invoker.code
|
96
115
|
end
|
97
116
|
end
|
@@ -144,20 +163,59 @@ context 'Invoker' do
|
|
144
163
|
end
|
145
164
|
end
|
146
165
|
|
147
|
-
test 'should copy default css to target directory if
|
166
|
+
test 'should copy default css to target directory if linkcss is specified' do
|
167
|
+
sample_outpath = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'sample-output.html'))
|
168
|
+
asciidoctor_stylesheet = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'asciidoctor.css'))
|
169
|
+
coderay_stylesheet = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'asciidoctor-coderay.css'))
|
170
|
+
begin
|
171
|
+
invoker = invoke_cli %W(-o #{sample_outpath} -a linkcss -a source-highlighter=coderay)
|
172
|
+
invoker.document
|
173
|
+
assert File.exist?(sample_outpath)
|
174
|
+
assert File.exist?(asciidoctor_stylesheet)
|
175
|
+
assert File.exist?(coderay_stylesheet)
|
176
|
+
ensure
|
177
|
+
FileUtils::rm_f(sample_outpath)
|
178
|
+
FileUtils::rm_f(asciidoctor_stylesheet)
|
179
|
+
FileUtils::rm_f(coderay_stylesheet)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
test 'should not copy default css to target directory if linkcss is set and copycss is unset' do
|
148
184
|
sample_outpath = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'sample-output.html'))
|
149
185
|
default_stylesheet = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'asciidoctor.css'))
|
150
186
|
begin
|
151
|
-
invoker = invoke_cli %W(-o #{sample_outpath} -a copycss)
|
187
|
+
invoker = invoke_cli %W(-o #{sample_outpath} -a linkcss -a copycss!)
|
152
188
|
invoker.document
|
153
189
|
assert File.exist?(sample_outpath)
|
154
|
-
assert File.exist?(default_stylesheet)
|
190
|
+
assert !File.exist?(default_stylesheet)
|
191
|
+
ensure
|
192
|
+
FileUtils::rm_f(sample_outpath)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
test 'should render all passed files' do
|
197
|
+
basic_outpath = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'basic.html'))
|
198
|
+
sample_outpath = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'sample.html'))
|
199
|
+
begin
|
200
|
+
invoke_cli_with_filenames %w(), %w(basic.asciidoc sample.asciidoc)
|
201
|
+
assert File.exist?(basic_outpath)
|
202
|
+
assert File.exist?(sample_outpath)
|
155
203
|
ensure
|
204
|
+
FileUtils::rm_f(basic_outpath)
|
156
205
|
FileUtils::rm_f(sample_outpath)
|
157
|
-
FileUtils::rm_f(default_stylesheet)
|
158
206
|
end
|
159
207
|
end
|
160
208
|
|
209
|
+
test 'should render all files that matches a glob expression' do
|
210
|
+
basic_outpath = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'basic.html'))
|
211
|
+
begin
|
212
|
+
invoke_cli_to_buffer %w(), "ba*.asciidoc"
|
213
|
+
assert File.exist?(basic_outpath)
|
214
|
+
ensure
|
215
|
+
FileUtils::rm_f(basic_outpath)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
161
219
|
test 'should suppress header footer if specified' do
|
162
220
|
invoker = invoke_cli_to_buffer %w(-s -o -)
|
163
221
|
output = invoker.read_output
|
@@ -208,7 +266,7 @@ context 'Invoker' do
|
|
208
266
|
assert_equal 'docbook45', doc.attr('backend')
|
209
267
|
assert_equal '.xml', doc.attr('outfilesuffix')
|
210
268
|
output = invoker.read_output
|
211
|
-
assert_xpath '/article', output, 1
|
269
|
+
assert_xpath '/xmlns:article', output, 1
|
212
270
|
end
|
213
271
|
|
214
272
|
test 'should set doctype to article if specified' do
|
@@ -227,6 +285,22 @@ context 'Invoker' do
|
|
227
285
|
assert_xpath '/html/body[@class="book"]', output, 1
|
228
286
|
end
|
229
287
|
|
288
|
+
test 'should locate custom templates based on template dir, template engine and backend' do
|
289
|
+
custom_backend_root = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends'))
|
290
|
+
invoker = invoke_cli_to_buffer %W(-E haml -T #{custom_backend_root} -o -)
|
291
|
+
doc = invoker.document
|
292
|
+
assert doc.renderer.views['block_paragraph'].is_a? Tilt::HamlTemplate
|
293
|
+
end
|
294
|
+
|
295
|
+
test 'should load custom templates from multiple template directories' do
|
296
|
+
custom_backend_1 = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends/haml/html5'))
|
297
|
+
custom_backend_2 = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'custom-backends/haml/html5-tweaks'))
|
298
|
+
invoker = invoke_cli_to_buffer %W(-T #{custom_backend_1} -T #{custom_backend_2} -o - -s)
|
299
|
+
output = invoker.read_output
|
300
|
+
assert_css '.paragraph', output, 0
|
301
|
+
assert_css '#preamble > .sectionbody > p', output, 1
|
302
|
+
end
|
303
|
+
|
230
304
|
test 'should set attribute with value' do
|
231
305
|
invoker = invoke_cli_to_buffer %w(--trace -a idprefix=id -s -o -)
|
232
306
|
doc = invoker.document
|
@@ -244,7 +318,7 @@ context 'Invoker' do
|
|
244
318
|
end
|
245
319
|
|
246
320
|
test 'should set attribute with quoted value containing a space' do
|
247
|
-
|
321
|
+
# emulating commandline arguments: --trace -a toc -a note-caption="Note to self:" -o -
|
248
322
|
invoker = invoke_cli_to_buffer %w(--trace -a toc -a note-caption=Note\ to\ self: -o -)
|
249
323
|
doc = invoker.document
|
250
324
|
assert_equal 'Note to self:', doc.attr('note-caption')
|
data/test/lexer_test.rb
CHANGED
@@ -7,6 +7,12 @@ context "Lexer" do
|
|
7
7
|
assert Asciidoctor::Lexer.is_section_title?('=== AsciiDoc Home Page')
|
8
8
|
end
|
9
9
|
|
10
|
+
test 'sanitize attribute name' do
|
11
|
+
assert_equal 'foobar', Asciidoctor::Lexer.sanitize_attribute_name("Foo Bar")
|
12
|
+
assert_equal 'foo', Asciidoctor::Lexer.sanitize_attribute_name("foo")
|
13
|
+
assert_equal 'foo3-bar', Asciidoctor::Lexer.sanitize_attribute_name("Foo 3^ # - Bar[")
|
14
|
+
end
|
15
|
+
|
10
16
|
test "collect unnamed attribute" do
|
11
17
|
attributes = {}
|
12
18
|
line = 'quote'
|
@@ -201,15 +207,17 @@ context "Lexer" do
|
|
201
207
|
assert_equal 'style#id.role', attributes[1]
|
202
208
|
end
|
203
209
|
|
204
|
-
test 'parse style attribute with style, role and
|
205
|
-
attributes = {1 => 'style.role#id'}
|
210
|
+
test 'parse style attribute with style, role, id and option' do
|
211
|
+
attributes = {1 => 'style.role#id%fragment'}
|
206
212
|
style, original_style = Asciidoctor::Lexer.parse_style_attribute(attributes)
|
207
213
|
assert_equal 'style', style
|
208
214
|
assert_nil original_style
|
209
215
|
assert_equal 'style', attributes['style']
|
210
216
|
assert_equal 'id', attributes['id']
|
211
217
|
assert_equal 'role', attributes['role']
|
212
|
-
assert_equal '
|
218
|
+
assert_equal '', attributes['fragment-option']
|
219
|
+
assert_equal 'fragment', attributes['options']
|
220
|
+
assert_equal 'style.role#id%fragment', attributes[1]
|
213
221
|
end
|
214
222
|
|
215
223
|
test 'parse style attribute with style, id and multiple roles' do
|
@@ -263,6 +271,16 @@ context "Lexer" do
|
|
263
271
|
assert_nil attributes[1]
|
264
272
|
end
|
265
273
|
|
274
|
+
test 'parse style attribute with option should preserve existing options' do
|
275
|
+
attributes = {1 => '%header', 'options' => 'footer', 'footer-option' => ''}
|
276
|
+
style, original_style = Asciidoctor::Lexer.parse_style_attribute(attributes)
|
277
|
+
assert_nil style
|
278
|
+
assert_nil original_style
|
279
|
+
assert_equal 'header,footer', attributes['options']
|
280
|
+
assert_equal '', attributes['header-option']
|
281
|
+
assert_equal '', attributes['footer-option']
|
282
|
+
end
|
283
|
+
|
266
284
|
test "parse author first" do
|
267
285
|
metadata, = parse_header_metadata 'Stuart'
|
268
286
|
assert_equal 5, metadata.size
|
data/test/links_test.rb
CHANGED
@@ -131,12 +131,44 @@ context 'Links' do
|
|
131
131
|
assert_xpath '//a[@href="#tigers"][text() = "About Tigers"]', render_string('<<tigers,"About Tigers">>'), 1
|
132
132
|
end
|
133
133
|
|
134
|
+
test 'xref using angled bracket syntax with path sans extension' do
|
135
|
+
doc = document_from_string '<<tigers#>>', :header_footer => false
|
136
|
+
assert_xpath '//a[@href="tigers.html"][text() = "[tigers]"]', doc.render, 1
|
137
|
+
end
|
138
|
+
|
139
|
+
test 'xref using angled bracket syntax with path and extension' do
|
140
|
+
doc = document_from_string '<<tigers.adoc#>>', :header_footer => false
|
141
|
+
assert_xpath '//a[@href="tigers.html"][text() = "[tigers]"]', doc.render, 1
|
142
|
+
end
|
143
|
+
|
144
|
+
test 'xref using angled bracket syntax with path and fragment' do
|
145
|
+
doc = document_from_string '<<tigers#about>>', :header_footer => false
|
146
|
+
assert_xpath '//a[@href="tigers.html#about"][text() = "[tigers#about]"]', doc.render, 1
|
147
|
+
end
|
148
|
+
|
149
|
+
test 'xref using angled bracket syntax with path, fragment and text' do
|
150
|
+
doc = document_from_string '<<tigers#about,About Tigers>>', :header_footer => false
|
151
|
+
assert_xpath '//a[@href="tigers.html#about"][text() = "About Tigers"]', doc.render, 1
|
152
|
+
end
|
153
|
+
|
154
|
+
test 'xref using angled bracket syntax with path which has been included in this document' do
|
155
|
+
doc = document_from_string '<<tigers#about,About Tigers>>', :header_footer => false
|
156
|
+
doc.references[:includes] << 'tigers'
|
157
|
+
assert_xpath '//a[@href="#about"][text() = "About Tigers"]', doc.render, 1
|
158
|
+
end
|
159
|
+
|
160
|
+
test 'xref using angled bracket syntax with nested path which has been included in this document' do
|
161
|
+
doc = document_from_string '<<part1/tigers#about,About Tigers>>', :header_footer => false
|
162
|
+
doc.references[:includes] << 'part1/tigers'
|
163
|
+
assert_xpath '//a[@href="#about"][text() = "About Tigers"]', doc.render, 1
|
164
|
+
end
|
165
|
+
|
134
166
|
test 'xref using angled bracket syntax inline with text' do
|
135
167
|
assert_xpath '//a[@href="#tigers"][text() = "about tigers"]', render_string('Want to learn <<tigers,about tigers>>?'), 1
|
136
168
|
end
|
137
169
|
|
138
170
|
test 'xref using angled bracket syntax with multi-line label inline with text' do
|
139
|
-
assert_xpath %{//a[@href="#tigers"][text() = "about
|
171
|
+
assert_xpath %{//a[@href="#tigers"][normalize-space(text()) = "about tigers"]}, render_string("Want to learn <<tigers,about\ntigers>>?"), 1
|
140
172
|
end
|
141
173
|
|
142
174
|
test 'xref with escaped text' do
|
@@ -162,7 +194,7 @@ context 'Links' do
|
|
162
194
|
end
|
163
195
|
|
164
196
|
test 'xref using macro syntax with multi-line label inline with text' do
|
165
|
-
assert_xpath %{//a[@href="#tigers"][text() = "about
|
197
|
+
assert_xpath %{//a[@href="#tigers"][normalize-space(text()) = "about tigers"]}, render_string("Want to learn xref:tigers[about\ntigers]?"), 1
|
166
198
|
end
|
167
199
|
|
168
200
|
test 'xref using invalid macro syntax does not create link' do
|
data/test/lists_test.rb
CHANGED
@@ -460,6 +460,20 @@ List
|
|
460
460
|
assert_xpath '//ul/li', output, 3
|
461
461
|
end
|
462
462
|
|
463
|
+
test 'should represent block style as style class' do
|
464
|
+
['disc', 'square', 'circle'].each do |style|
|
465
|
+
input = <<-EOS
|
466
|
+
[#{style}]
|
467
|
+
* a
|
468
|
+
* b
|
469
|
+
* c
|
470
|
+
EOS
|
471
|
+
output = render_embedded_string input
|
472
|
+
assert_css ".ulist.#{style}", output, 1
|
473
|
+
assert_css ".ulist.#{style} ul.#{style}", output, 1
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
463
477
|
test "asterisk elements separated by blank lines should merge lists" do
|
464
478
|
input = <<-EOS
|
465
479
|
List
|
@@ -1075,7 +1089,7 @@ Lists
|
|
1075
1089
|
assert_xpath '//ul/li[1]/*', output, 1
|
1076
1090
|
end
|
1077
1091
|
|
1078
|
-
test
|
1092
|
+
test 'consecutive blocks in list continuation attach to list item' do
|
1079
1093
|
input = <<-EOS
|
1080
1094
|
Lists
|
1081
1095
|
=====
|
@@ -1092,7 +1106,7 @@ ____
|
|
1092
1106
|
+
|
1093
1107
|
* Item two
|
1094
1108
|
EOS
|
1095
|
-
output =
|
1109
|
+
output = render_embedded_string input
|
1096
1110
|
assert_xpath '//ul', output, 1
|
1097
1111
|
assert_xpath '//ul/li', output, 2
|
1098
1112
|
assert_xpath '//ul/li[1]/p', output, 1
|
@@ -1453,6 +1467,58 @@ List
|
|
1453
1467
|
assert_xpath '//ol/li', output, 3
|
1454
1468
|
end
|
1455
1469
|
|
1470
|
+
test 'should represent explicit role attribute as style class' do
|
1471
|
+
input = <<-EOS
|
1472
|
+
[role="dry"]
|
1473
|
+
. Once
|
1474
|
+
. Again
|
1475
|
+
. Refactor!
|
1476
|
+
EOS
|
1477
|
+
|
1478
|
+
output = render_embedded_string input
|
1479
|
+
assert_css '.olist.arabic.dry', output, 1
|
1480
|
+
assert_css '.olist ol.arabic', output, 1
|
1481
|
+
end
|
1482
|
+
|
1483
|
+
test 'should represent custom numbering and explicit role attribute as style classes' do
|
1484
|
+
input = <<-EOS
|
1485
|
+
[loweralpha, role="dry"]
|
1486
|
+
. Once
|
1487
|
+
. Again
|
1488
|
+
. Refactor!
|
1489
|
+
EOS
|
1490
|
+
|
1491
|
+
output = render_embedded_string input
|
1492
|
+
assert_css '.olist.loweralpha.dry', output, 1
|
1493
|
+
assert_css '.olist ol.loweralpha', output, 1
|
1494
|
+
end
|
1495
|
+
|
1496
|
+
test 'should represent implicit role attribute as style class' do
|
1497
|
+
input = <<-EOS
|
1498
|
+
[.dry]
|
1499
|
+
. Once
|
1500
|
+
. Again
|
1501
|
+
. Refactor!
|
1502
|
+
EOS
|
1503
|
+
|
1504
|
+
output = render_embedded_string input
|
1505
|
+
assert_css '.olist.arabic.dry', output, 1
|
1506
|
+
assert_css '.olist ol.arabic', output, 1
|
1507
|
+
end
|
1508
|
+
|
1509
|
+
test 'should represent custom numbering and implicit role attribute as style classes' do
|
1510
|
+
input = <<-EOS
|
1511
|
+
[loweralpha.dry]
|
1512
|
+
. Once
|
1513
|
+
. Again
|
1514
|
+
. Refactor!
|
1515
|
+
EOS
|
1516
|
+
|
1517
|
+
output = render_embedded_string input
|
1518
|
+
assert_css '.olist.loweralpha.dry', output, 1
|
1519
|
+
assert_css '.olist ol.loweralpha', output, 1
|
1520
|
+
end
|
1521
|
+
|
1456
1522
|
test "dot elements separated by blank lines should merge lists" do
|
1457
1523
|
input = <<-EOS
|
1458
1524
|
List
|
@@ -1682,6 +1748,25 @@ term2::
|
|
1682
1748
|
assert_xpath '(//dl/dt)[2]/following-sibling::dd/p[text() = "def2"]', output, 1
|
1683
1749
|
end
|
1684
1750
|
|
1751
|
+
test 'multi-line element with paragraph starting with multiple dashes should not be seen as list' do
|
1752
|
+
input = <<-EOS
|
1753
|
+
term1::
|
1754
|
+
def1
|
1755
|
+
-- and a note
|
1756
|
+
|
1757
|
+
term2::
|
1758
|
+
def2
|
1759
|
+
EOS
|
1760
|
+
output = render_embedded_string input
|
1761
|
+
assert_xpath '//dl', output, 1
|
1762
|
+
assert_xpath '//dl/dt', output, 2
|
1763
|
+
assert_xpath '//dl/dt/following-sibling::dd', output, 2
|
1764
|
+
assert_xpath '(//dl/dt)[1][normalize-space(text()) = "term1"]', output, 1
|
1765
|
+
assert_xpath %((//dl/dt)[1]/following-sibling::dd/p[text() = "def1#{entity 8201}#{entity 8212}#{entity 8201}and a note"]), output, 1
|
1766
|
+
assert_xpath '(//dl/dt)[2][normalize-space(text()) = "term2"]', output, 1
|
1767
|
+
assert_xpath '(//dl/dt)[2]/following-sibling::dd/p[text() = "def2"]', output, 1
|
1768
|
+
end
|
1769
|
+
|
1685
1770
|
test "multi-line element with multiple terms" do
|
1686
1771
|
input = <<-EOS
|
1687
1772
|
term1::
|
@@ -2023,6 +2108,23 @@ A new paragraph.
|
|
2023
2108
|
assert_xpath '//*[@class="dlist"]/following-sibling::*[@class="paragraph"]', output, 1
|
2024
2109
|
assert_xpath '(//*[@class="dlist"]/following-sibling::*[@class="paragraph"])[1]/p[text() = "A new paragraph."]', output, 1
|
2025
2110
|
end
|
2111
|
+
|
2112
|
+
test 'should not match comment line that looks like labeled list term' do
|
2113
|
+
input = <<-EOS
|
2114
|
+
* item
|
2115
|
+
|
2116
|
+
//::
|
2117
|
+
== Section
|
2118
|
+
|
2119
|
+
section text
|
2120
|
+
EOS
|
2121
|
+
|
2122
|
+
output = render_embedded_string input
|
2123
|
+
assert_xpath '/*[@class="ulist"]', output, 1
|
2124
|
+
assert_xpath '/*[@class="sect1"]', output, 1
|
2125
|
+
assert_xpath '/*[@class="sect1"]/h2[text()="Section"]', output, 1
|
2126
|
+
assert_xpath '/*[@class="ulist"]/following-sibling::*[@class="sect1"]', output, 1
|
2127
|
+
end
|
2026
2128
|
end
|
2027
2129
|
|
2028
2130
|
context "Nested lists" do
|
@@ -2284,6 +2386,17 @@ term:: def
|
|
2284
2386
|
assert_xpath '(//table/colgroup/col)[2][@style="width:75%;"]', output, 1
|
2285
2387
|
end
|
2286
2388
|
|
2389
|
+
test 'should add strong class to label if strong option is set' do
|
2390
|
+
input = <<-EOS
|
2391
|
+
[horizontal, options="strong"]
|
2392
|
+
term:: def
|
2393
|
+
EOS
|
2394
|
+
|
2395
|
+
output = render_embedded_string input
|
2396
|
+
assert_css '.hdlist', output, 1
|
2397
|
+
assert_css '.hdlist td.hdlist1.strong', output, 1
|
2398
|
+
end
|
2399
|
+
|
2287
2400
|
test 'consecutive terms in horizontal list should share same cell' do
|
2288
2401
|
input = <<-EOS
|
2289
2402
|
[horizontal]
|
@@ -2296,7 +2409,9 @@ last::
|
|
2296
2409
|
output = render_embedded_string input
|
2297
2410
|
assert_xpath '//tr', output, 2
|
2298
2411
|
assert_xpath '(//tr)[1]/td[@class="hdlist1"]', output, 1
|
2299
|
-
|
2412
|
+
# NOTE I'm trimming the trailing <br> in Asciidoctor
|
2413
|
+
#assert_xpath '(//tr)[1]/td[@class="hdlist1"]/br', output, 2
|
2414
|
+
assert_xpath '(//tr)[1]/td[@class="hdlist1"]/br', output, 1
|
2300
2415
|
assert_xpath '(//tr)[2]/td[@class="hdlist2"]', output, 1
|
2301
2416
|
end
|
2302
2417
|
|
@@ -3631,6 +3746,121 @@ require 'asciidoctor' # \\<1>
|
|
3631
3746
|
assert_xpath '//co', output, 0
|
3632
3747
|
end
|
3633
3748
|
|
3749
|
+
test 'should not recognize callouts in middle of line' do
|
3750
|
+
input = <<-EOS
|
3751
|
+
[source, ruby]
|
3752
|
+
----
|
3753
|
+
puts "The syntax <1> at the end of the line makes a code callout"
|
3754
|
+
----
|
3755
|
+
EOS
|
3756
|
+
output = render_embedded_string input
|
3757
|
+
assert_xpath '//b', output, 0
|
3758
|
+
end
|
3759
|
+
|
3760
|
+
test 'should allow multiple callouts on the same line' do
|
3761
|
+
input = <<-EOS
|
3762
|
+
[source, ruby]
|
3763
|
+
----
|
3764
|
+
require 'asciidoctor' <1>
|
3765
|
+
doc = Asciidoctor.load('Hello, World!') # <2> <3> <4>
|
3766
|
+
puts doc.render <5><6>
|
3767
|
+
exit 0
|
3768
|
+
----
|
3769
|
+
<1> Require library
|
3770
|
+
<2> Load document from String
|
3771
|
+
<3> Uses default backend and doctype
|
3772
|
+
<4> One more for good luck
|
3773
|
+
<5> Renders document to String
|
3774
|
+
<6> Prints output to stdout
|
3775
|
+
EOS
|
3776
|
+
output = render_embedded_string input
|
3777
|
+
assert_xpath '//code/b', output, 6
|
3778
|
+
assert_match(/ <b>\(1\)<\/b>$/, output)
|
3779
|
+
assert_match(/ <b>\(2\)<\/b> <b>\(3\)<\/b> <b>\(4\)<\/b>$/, output)
|
3780
|
+
assert_match(/ <b>\(5\)<\/b><b>\(6\)<\/b>$/, output)
|
3781
|
+
end
|
3782
|
+
|
3783
|
+
test 'should allow XML comment-style callouts' do
|
3784
|
+
input = <<-EOS
|
3785
|
+
[source, xml]
|
3786
|
+
----
|
3787
|
+
<section>
|
3788
|
+
<title>Section Title</title> <!--1-->
|
3789
|
+
<simpara>Just a paragraph</simpara> <!--2-->
|
3790
|
+
</section>
|
3791
|
+
----
|
3792
|
+
<1> The title is required
|
3793
|
+
<2> The content isn't
|
3794
|
+
EOS
|
3795
|
+
output = render_embedded_string input
|
3796
|
+
assert_xpath '//b', output, 2
|
3797
|
+
assert_xpath '//b[text()="(1)"]', output, 1
|
3798
|
+
assert_xpath '//b[text()="(2)"]', output, 1
|
3799
|
+
end
|
3800
|
+
|
3801
|
+
test 'should not allow callouts with half an XML comment' do
|
3802
|
+
input = <<-EOS
|
3803
|
+
----
|
3804
|
+
First line <1-->
|
3805
|
+
Second line <2-->
|
3806
|
+
----
|
3807
|
+
EOS
|
3808
|
+
output = render_embedded_string input
|
3809
|
+
assert_xpath '//b', output, 0
|
3810
|
+
end
|
3811
|
+
|
3812
|
+
test 'should not recognize callouts in an indented labeled list paragraph' do
|
3813
|
+
input = <<-EOS
|
3814
|
+
foo::
|
3815
|
+
bar <1>
|
3816
|
+
|
3817
|
+
<1> Not pointing to a callout
|
3818
|
+
EOS
|
3819
|
+
output = render_embedded_string input
|
3820
|
+
assert_xpath '//dl//b', output, 0
|
3821
|
+
assert_xpath '//dl/dd/p[text()="bar <1>"]', output, 1
|
3822
|
+
assert_xpath '//ol/li/p[text()="Not pointing to a callout"]', output, 1
|
3823
|
+
end
|
3824
|
+
|
3825
|
+
test 'should not recognize callouts in an indented outline list paragraph' do
|
3826
|
+
input = <<-EOS
|
3827
|
+
* foo
|
3828
|
+
bar <1>
|
3829
|
+
|
3830
|
+
<1> Not pointing to a callout
|
3831
|
+
EOS
|
3832
|
+
output = render_embedded_string input
|
3833
|
+
assert_xpath '//ul//b', output, 0
|
3834
|
+
assert_xpath %(//ul/li/p[text()="foo\nbar <1>"]), output, 1
|
3835
|
+
assert_xpath '//ol/li/p[text()="Not pointing to a callout"]', output, 1
|
3836
|
+
end
|
3837
|
+
|
3838
|
+
test 'should remove leading line comment chars' do
|
3839
|
+
input = <<-EOS
|
3840
|
+
----
|
3841
|
+
puts 'Hello, world!' # <1>
|
3842
|
+
----
|
3843
|
+
<1> Ruby
|
3844
|
+
|
3845
|
+
----
|
3846
|
+
println 'Hello, world!' // <1>
|
3847
|
+
----
|
3848
|
+
<1> Groovy
|
3849
|
+
|
3850
|
+
----
|
3851
|
+
(def hello (fn [] "Hello, world!")) ;; <1>
|
3852
|
+
(hello)
|
3853
|
+
----
|
3854
|
+
<1> Clojure
|
3855
|
+
EOS
|
3856
|
+
output = render_embedded_string input
|
3857
|
+
assert_xpath '//b', output, 3
|
3858
|
+
nodes = xmlnodes_at_css 'pre', output
|
3859
|
+
assert_equal "puts 'Hello, world!' (1)", nodes[0].text
|
3860
|
+
assert_equal "println 'Hello, world!' (1)", nodes[1].text
|
3861
|
+
assert_equal %((def hello (fn [] "Hello, world!")) (1)\n(hello)), nodes[2].text
|
3862
|
+
end
|
3863
|
+
|
3634
3864
|
test 'literal block with callouts' do
|
3635
3865
|
input = <<-EOS
|
3636
3866
|
....
|
@@ -3680,8 +3910,8 @@ puts doc.render # <3>
|
|
3680
3910
|
[source]
|
3681
3911
|
----
|
3682
3912
|
require 'asciidoctor' # <1>
|
3683
|
-
doc = Asciidoctor::Document.new('Hello, World!')
|
3684
|
-
puts doc.render
|
3913
|
+
doc = Asciidoctor::Document.new('Hello, World!') #<2>
|
3914
|
+
puts doc.render #<3>
|
3685
3915
|
----
|
3686
3916
|
<1> Describe the first line
|
3687
3917
|
<2> Describe the second line
|
@@ -3690,11 +3920,78 @@ puts doc.render # <3>
|
|
3690
3920
|
output = render_embedded_string input, :attributes => {'icons' => 'font'}
|
3691
3921
|
assert_css '.listingblock code > i', output, 3
|
3692
3922
|
(1..3).each do |i|
|
3693
|
-
assert_xpath %((/div[@class="listingblock"]//code/i)[#{i}]
|
3923
|
+
assert_xpath %((/div[@class="listingblock"]//code/i)[#{i}]), output, 1
|
3924
|
+
assert_xpath %((/div[@class="listingblock"]//code/i)[#{i}][@class="conum"][@data-value="#{i}"]), output, 1
|
3925
|
+
assert_xpath %((/div[@class="listingblock"]//code/i)[#{i}]/following-sibling::b[text()="(#{i})"]), output, 1
|
3694
3926
|
end
|
3695
3927
|
assert_css '.colist table td i', output, 3
|
3696
3928
|
(1..3).each do |i|
|
3697
|
-
assert_xpath %((/div[@class="colist arabic"]//td/i)[#{i}]
|
3929
|
+
assert_xpath %((/div[@class="colist arabic"]//td/i)[#{i}]), output, 1
|
3930
|
+
assert_xpath %((/div[@class="colist arabic"]//td/i)[#{i}][@class="conum"][@data-value = "#{i}"]), output, 1
|
3931
|
+
assert_xpath %((/div[@class="colist arabic"]//td/i)[#{i}]/following-sibling::b[text() = "#{i}"]), output, 1
|
3698
3932
|
end
|
3699
3933
|
end
|
3700
3934
|
end
|
3935
|
+
|
3936
|
+
context 'Checklists' do
|
3937
|
+
test 'should create checklist if at least one item has checkbox syntax' do
|
3938
|
+
input = <<-EOS
|
3939
|
+
- [ ] todo
|
3940
|
+
- [x] done
|
3941
|
+
- plain
|
3942
|
+
EOS
|
3943
|
+
|
3944
|
+
output = render_embedded_string input
|
3945
|
+
assert_css '.ulist.checklist', output, 1
|
3946
|
+
assert_css '.ulist.checklist li input[type="checkbox"][disabled]', output, 2
|
3947
|
+
assert_css '.ulist.checklist li input[type="checkbox"][checked]', output, 1
|
3948
|
+
assert_xpath '(/*[@class="ulist checklist"]/ul/li)[3]/p[text()="plain"]', output, 1
|
3949
|
+
end
|
3950
|
+
|
3951
|
+
test 'should create checklist with font icons if at least one item has checkbox syntax and icons attribute is font' do
|
3952
|
+
input = <<-EOS
|
3953
|
+
- [ ] todo
|
3954
|
+
- [x] done
|
3955
|
+
- plain
|
3956
|
+
EOS
|
3957
|
+
|
3958
|
+
output = render_embedded_string input, :attributes => {'icons' => 'font'}
|
3959
|
+
assert_css '.ulist.checklist', output, 1
|
3960
|
+
assert_css '.ulist.checklist li i.icon-check', output, 1
|
3961
|
+
assert_css '.ulist.checklist li i.icon-check-empty', output, 1
|
3962
|
+
assert_xpath '(/*[@class="ulist checklist"]/ul/li)[3]/p[text()="plain"]', output, 1
|
3963
|
+
end
|
3964
|
+
|
3965
|
+
test 'should create interactive checklist if interactive option is set even with icons attribute is font' do
|
3966
|
+
input = <<-EOS
|
3967
|
+
:icons: font
|
3968
|
+
|
3969
|
+
[options="interactive"]
|
3970
|
+
- [ ] todo
|
3971
|
+
- [x] done
|
3972
|
+
EOS
|
3973
|
+
|
3974
|
+
output = render_embedded_string input
|
3975
|
+
assert_css '.ulist.checklist', output, 1
|
3976
|
+
assert_css '.ulist.checklist li input[type="checkbox"]', output, 2
|
3977
|
+
assert_css '.ulist.checklist li input[type="checkbox"][disabled]', output, 0
|
3978
|
+
assert_css '.ulist.checklist li input[type="checkbox"][checked]', output, 1
|
3979
|
+
end
|
3980
|
+
end
|
3981
|
+
|
3982
|
+
context 'Lists model' do
|
3983
|
+
test 'content should return items in list' do
|
3984
|
+
input = <<-EOS
|
3985
|
+
* one
|
3986
|
+
* two
|
3987
|
+
* three
|
3988
|
+
EOS
|
3989
|
+
|
3990
|
+
doc = document_from_string input
|
3991
|
+
list = doc.blocks.first
|
3992
|
+
assert list.is_a? Asciidoctor::List
|
3993
|
+
items = list.items
|
3994
|
+
assert_equal 3, items.size
|
3995
|
+
assert_equal list.items, list.content
|
3996
|
+
end
|
3997
|
+
end
|