asciidoctor 1.5.5 → 1.5.6
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 +216 -1
- data/CONTRIBUTING.adoc +2 -2
- data/Gemfile +20 -1
- data/LICENSE.adoc +1 -1
- data/README-fr.adoc +4 -3
- data/README-jp.adoc +11 -10
- data/README-zh_CN.adoc +4 -3
- data/README.adoc +17 -202
- data/Rakefile +41 -25
- data/asciidoctor.gemspec +9 -10
- data/data/locale/attributes.adoc +216 -34
- data/data/stylesheets/asciidoctor-default.css +23 -16
- data/features/step_definitions.rb +15 -19
- data/features/xref.feature +584 -20
- data/lib/asciidoctor.rb +292 -278
- data/lib/asciidoctor/abstract_block.rb +155 -94
- data/lib/asciidoctor/abstract_node.rb +108 -94
- data/lib/asciidoctor/attribute_list.rb +30 -22
- data/lib/asciidoctor/block.rb +7 -7
- data/lib/asciidoctor/cli/invoker.rb +47 -34
- data/lib/asciidoctor/cli/options.rb +22 -11
- data/lib/asciidoctor/converter.rb +3 -3
- data/lib/asciidoctor/converter/base.rb +2 -2
- data/lib/asciidoctor/converter/composite.rb +1 -1
- data/lib/asciidoctor/converter/docbook45.rb +2 -2
- data/lib/asciidoctor/converter/docbook5.rb +132 -87
- data/lib/asciidoctor/converter/factory.rb +0 -1
- data/lib/asciidoctor/converter/html5.rb +116 -98
- data/lib/asciidoctor/converter/manpage.rb +51 -52
- data/lib/asciidoctor/converter/template.rb +47 -36
- data/lib/asciidoctor/core_ext.rb +8 -2
- data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +4 -0
- data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +6 -0
- data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +5 -0
- data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +1 -1
- data/lib/asciidoctor/core_ext/1.8.7/string/{limit.rb → limit_bytesize.rb} +7 -6
- data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +6 -0
- data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +1 -1
- data/lib/asciidoctor/core_ext/nil_or_empty.rb +5 -5
- data/lib/asciidoctor/core_ext/regexp/is_match.rb +3 -0
- data/lib/asciidoctor/core_ext/string/{limit.rb → limit_bytesize.rb} +2 -2
- data/lib/asciidoctor/document.rb +216 -213
- data/lib/asciidoctor/extensions.rb +318 -185
- data/lib/asciidoctor/helpers.rb +35 -35
- data/lib/asciidoctor/inline.rb +32 -1
- data/lib/asciidoctor/list.rb +22 -6
- data/lib/asciidoctor/parser.rb +1008 -1038
- data/lib/asciidoctor/path_resolver.rb +46 -50
- data/lib/asciidoctor/reader.rb +275 -251
- data/lib/asciidoctor/section.rb +86 -58
- data/lib/asciidoctor/stylesheets.rb +6 -6
- data/lib/asciidoctor/substitutors.rb +567 -649
- data/lib/asciidoctor/table.rb +163 -108
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +18 -16
- data/man/asciidoctor.adoc +15 -13
- data/test/attributes_test.rb +138 -22
- data/test/blocks_test.rb +377 -97
- data/test/converter_test.rb +13 -0
- data/test/document_test.rb +244 -34
- data/test/extensions_test.rb +409 -42
- data/test/fixtures/asciidoc_index.txt +521 -0
- data/test/fixtures/basic-docinfo-footer.html +6 -0
- data/test/fixtures/basic-docinfo-footer.xml +8 -0
- data/test/fixtures/basic-docinfo.html +1 -0
- data/test/fixtures/basic-docinfo.xml +4 -0
- data/test/fixtures/basic.asciidoc +5 -0
- data/test/fixtures/chapter-a.adoc +3 -0
- data/test/fixtures/child-include.adoc +5 -0
- data/test/fixtures/circle.svg +9 -0
- data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +6 -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/custom-docinfodir/basic-docinfo.html +1 -0
- data/test/fixtures/custom-docinfodir/docinfo.html +1 -0
- data/test/fixtures/docinfo-footer.html +1 -0
- data/test/fixtures/docinfo-footer.xml +9 -0
- data/test/fixtures/docinfo.html +1 -0
- data/test/fixtures/docinfo.xml +3 -0
- data/test/fixtures/dot.gif +0 -0
- data/test/fixtures/encoding.asciidoc +13 -0
- data/test/fixtures/grandchild-include.adoc +3 -0
- data/test/fixtures/hello-asciidoctor.pdf +69 -0
- data/test/fixtures/include-file.asciidoc +24 -0
- data/test/fixtures/include-file.ml +3 -0
- data/test/fixtures/include-file.xml +5 -0
- data/test/fixtures/master.adoc +5 -0
- data/test/fixtures/mismatched-end-tag.adoc +7 -0
- data/test/fixtures/parent-include-restricted.adoc +5 -0
- data/test/fixtures/parent-include.adoc +5 -0
- data/test/fixtures/sample.asciidoc +26 -0
- data/test/fixtures/stylesheets/custom.css +3 -0
- data/test/fixtures/subs-docinfo.html +2 -0
- data/test/fixtures/subs.adoc +7 -0
- data/test/fixtures/tagged-class-enclosed.rb +26 -0
- data/test/fixtures/tagged-class.rb +23 -0
- data/test/fixtures/tip.gif +0 -0
- data/test/invoker_test.rb +82 -4
- data/test/links_test.rb +312 -37
- data/test/lists_test.rb +204 -25
- data/test/manpage_test.rb +191 -4
- data/test/options_test.rb +18 -1
- data/test/paragraphs_test.rb +32 -7
- data/test/parser_test.rb +150 -30
- data/test/paths_test.rb +47 -13
- data/test/preamble_test.rb +1 -1
- data/test/reader_test.rb +366 -126
- data/test/sections_test.rb +203 -56
- data/test/substitutions_test.rb +339 -131
- data/test/tables_test.rb +315 -15
- data/test/test_helper.rb +400 -0
- data/test/text_test.rb +5 -5
- metadata +110 -22
data/man/asciidoctor.adoc
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
Dan Allen; Sarah White; Ryan Waldron
|
3
3
|
:doctype: manpage
|
4
4
|
:man manual: Asciidoctor Manual
|
5
|
-
:man source: Asciidoctor 1.5.
|
5
|
+
:man source: Asciidoctor 1.5.6
|
6
6
|
:page-layout: base
|
7
7
|
|
8
8
|
== NAME
|
@@ -26,7 +26,7 @@ If _FILE_ is _-_ then the AsciiDoc source is read from standard input.
|
|
26
26
|
*-B, --base-dir*=_DIR_::
|
27
27
|
Base directory containing the document and resources.
|
28
28
|
Defaults to the directory containing the source file, or the working directory if the source is read from a stream.
|
29
|
-
|
29
|
+
When combined with the safe mode setting, can be used to chroot the execution of the program.
|
30
30
|
|
31
31
|
*-S, --safe-mode*=_SAFE_MODE_::
|
32
32
|
Set safe mode level: _unsafe_, _safe_, _server_ or _secure_.
|
@@ -35,7 +35,7 @@ If _FILE_ is _-_ then the AsciiDoc source is read from standard input.
|
|
35
35
|
|
36
36
|
*--safe*::
|
37
37
|
Set safe mode level to _safe_.
|
38
|
-
Enables include
|
38
|
+
Enables include directives, but prevents access to ancestor paths of source file.
|
39
39
|
Provided for compatibility with the asciidoc command.
|
40
40
|
If not set, the safe mode level defaults to _unsafe_ when Asciidoctor is invoked using this script.
|
41
41
|
|
@@ -43,7 +43,7 @@ If _FILE_ is _-_ then the AsciiDoc source is read from standard input.
|
|
43
43
|
|
44
44
|
*-a, --attribute*=_ATTRIBUTE_::
|
45
45
|
Define, override or delete a document attribute.
|
46
|
-
Command-line attributes take precedence over attributes defined in the source file.
|
46
|
+
Command-line attributes take precedence over attributes defined in the source file unless the value ends with _@_.
|
47
47
|
+
|
48
48
|
_ATTRIBUTE_ is normally formatted as a key-value pair, in the form _NAME=VALUE_.
|
49
49
|
Alternate acceptable forms are _NAME_ (where the _VALUE_ defaults to an empty string), _NAME!_ (unassigns the _NAME_ attribute) and _NAME=VALUE@_ (where _VALUE_ does not override value of _NAME_ attribute if it's already defined in the source document).
|
@@ -54,14 +54,14 @@ This option may be specified more than once.
|
|
54
54
|
*-b, --backend*=_BACKEND_::
|
55
55
|
Backend output file format: _html5_, _docbook5_, _docbook45_ and _manpage_ are supported out of the box.
|
56
56
|
You can also use the backend alias names _html_ (aliased to _html5_) or _docbook_ (aliased to _docbook5_).
|
57
|
+
Other values can be passed, but if Asciidoctor cannot resolve the backend to a converter, it will fail.
|
57
58
|
Defaults to _html5_.
|
58
|
-
Other options can be passed, but if Asciidoctor cannot find the backend, it will fail during conversion.
|
59
59
|
|
60
60
|
*-d, --doctype*=_DOCTYPE_::
|
61
61
|
Document type: _article_, _book_, _manpage_ or _inline_.
|
62
62
|
Sets the root element when using the _docbook_ backend and the style class on the HTML body element when using the _html_ backend.
|
63
63
|
The _book_ document type allows multiple level-0 section titles in a single document.
|
64
|
-
The _manpage_ document type enables parsing of metadata necessary to produce a
|
64
|
+
The _manpage_ document type enables parsing of metadata necessary to produce a man page.
|
65
65
|
The _inline_ document type allows the content of a single paragraph to be formatted and returned without wrapping it in a containing element.
|
66
66
|
Defaults to _article_.
|
67
67
|
|
@@ -98,9 +98,9 @@ This option may be specified more than once.
|
|
98
98
|
*-o, --out-file*=_OUT_FILE_::
|
99
99
|
Write output to file _OUT_FILE_.
|
100
100
|
Defaults to the base name of the input file suffixed with _backend_ extension.
|
101
|
-
|
102
|
-
If
|
103
|
-
If
|
101
|
+
The file is resolved relative to the working directory.
|
102
|
+
If the input is read from standard input or a named pipe (fifo), then the output file defaults to stdout.
|
103
|
+
If _OUT_FILE_ is _-_, then the output file is written to standard output.
|
104
104
|
|
105
105
|
*-r, --require*=_LIBRARY_::
|
106
106
|
Require the specified library before executing the processor, using the standard Ruby require.
|
@@ -136,8 +136,10 @@ Matching templates found in subsequent directories override ones previously disc
|
|
136
136
|
|
137
137
|
=== Program Information
|
138
138
|
|
139
|
-
*-h, --help
|
140
|
-
|
139
|
+
*-h, --help* [_TOPIC_]::
|
140
|
+
Print the help message.
|
141
|
+
Show the command usage if _TOPIC_ is not specified (or not recognized).
|
142
|
+
Dump the Asciidoctor man page (in troff/groff format) if _TOPIC_ is _manpage_.
|
141
143
|
|
142
144
|
*-V, --version*::
|
143
145
|
Print program version number.
|
@@ -146,7 +148,7 @@ Matching templates found in subsequent directories override ones previously disc
|
|
146
148
|
|
147
149
|
== ENVIRONMENT
|
148
150
|
|
149
|
-
*Asciidoctor* honors the SOURCE_DATE_EPOCH environment variable.
|
151
|
+
*Asciidoctor* honors the *SOURCE_DATE_EPOCH* environment variable.
|
150
152
|
If this variable is assigned an integer value, that value is used as the epoch of all input documents and as the local date and time.
|
151
153
|
See https://reproducible-builds.org/specs/source-date-epoch/ for more information about this environment variable.
|
152
154
|
|
@@ -180,5 +182,5 @@ Refer to the *Asciidoctor* issue tracker at https://github.com/asciidoctor/ascii
|
|
180
182
|
|
181
183
|
== COPYING
|
182
184
|
|
183
|
-
Copyright \(C) 2012-
|
185
|
+
Copyright \(C) 2012-2017 Dan Allen, Ryan Waldron and the Asciidoctor Project.
|
184
186
|
Free use of this software is granted under the terms of the MIT License.
|
data/test/attributes_test.rb
CHANGED
@@ -46,6 +46,16 @@ linus.torvalds@example.com
|
|
46
46
|
assert_equal %(Linus Torvalds +\nLinux Hacker +\nlinus.torvalds@example.com), doc.attributes['signature']
|
47
47
|
end
|
48
48
|
|
49
|
+
test 'should allow pass macro to surround a multi-line value that contains line breaks' do
|
50
|
+
str = <<-EOS
|
51
|
+
:signature: pass:a[{author} + \\
|
52
|
+
{title} + \\
|
53
|
+
{email}]
|
54
|
+
EOS
|
55
|
+
doc = document_from_string str, :attributes => { 'author' => 'Linus Torvalds', 'title' => 'Linux Hacker', 'email' => 'linus.torvalds@example.com' }
|
56
|
+
assert_equal %(Linus Torvalds +\nLinux Hacker +\nlinus.torvalds@example.com), (doc.attr 'signature')
|
57
|
+
end
|
58
|
+
|
49
59
|
test 'should delete an attribute that ends with !' do
|
50
60
|
doc = document_from_string(":frog: Tanglefoot\n:frog!:")
|
51
61
|
assert_equal nil, doc.attributes['frog']
|
@@ -86,14 +96,25 @@ linus.torvalds@example.com
|
|
86
96
|
assert_equal 'Asciidoctor 1.0', doc.attributes['release']
|
87
97
|
end
|
88
98
|
|
89
|
-
test
|
90
|
-
|
99
|
+
test 'assigns attribute to empty string if substitution fails to resolve attribute' do
|
100
|
+
input = ':release: Asciidoctor {version}'
|
101
|
+
doc, warnings = redirect_streams do |_, err|
|
102
|
+
[(document_from_string input, :attributes => { 'attribute-missing' => 'drop-line' }), err.string]
|
103
|
+
end
|
91
104
|
assert_equal '', doc.attributes['release']
|
105
|
+
assert_includes warnings, 'dropping line containing reference to missing attribute'
|
92
106
|
end
|
93
107
|
|
94
|
-
test
|
95
|
-
|
108
|
+
test 'assigns multi-line attribute to empty string if substitution fails to resolve attribute' do
|
109
|
+
input = <<-EOS
|
110
|
+
:release: Asciidoctor +
|
111
|
+
{version}
|
112
|
+
EOS
|
113
|
+
doc, warnings = redirect_streams do |_, err|
|
114
|
+
[(document_from_string input, :attributes => { 'attribute-missing' => 'drop-line' }), err.string]
|
115
|
+
end
|
96
116
|
assert_equal '', doc.attributes['release']
|
117
|
+
assert_includes warnings, 'dropping line containing reference to missing attribute'
|
97
118
|
end
|
98
119
|
|
99
120
|
test 'resolves attributes inside attribute value within header' do
|
@@ -213,6 +234,13 @@ EOS
|
|
213
234
|
assert_equal '<>&', doc.attributes['xml-busters']
|
214
235
|
end
|
215
236
|
|
237
|
+
test 'should not recognize pass macro with invalid substitution list in attribute value' do
|
238
|
+
[',', '42', 'a,'].each do |subs|
|
239
|
+
doc = document_from_string %(:pass-fail: pass:#{subs}[whale])
|
240
|
+
assert_equal %(pass:#{subs}[whale]), doc.attributes['pass-fail']
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
216
244
|
test "attribute is treated as defined until it's not" do
|
217
245
|
input = <<-EOS
|
218
246
|
:holygrail:
|
@@ -350,6 +378,19 @@ content
|
|
350
378
|
assert doc.attributes.has_key? 'basebackend-html'
|
351
379
|
end
|
352
380
|
|
381
|
+
test 'set_attr should set value to empty string if no value is specified' do
|
382
|
+
node = Asciidoctor::Block.new nil, :paragraph, :attributes => {}
|
383
|
+
node.set_attr 'foo'
|
384
|
+
assert_equal '', (node.attr 'foo')
|
385
|
+
end
|
386
|
+
|
387
|
+
test 'remove_attr should remove attribute and return previous value' do
|
388
|
+
doc = empty_document
|
389
|
+
node = Asciidoctor::Block.new doc, :paragraph, :attributes => { 'foo' => 'bar' }
|
390
|
+
assert_equal 'bar', (node.remove_attr 'foo')
|
391
|
+
assert_nil node.attr('foo')
|
392
|
+
end
|
393
|
+
|
353
394
|
test 'set_attr should not overwrite existing key if overwrite is false' do
|
354
395
|
node = Asciidoctor::Block.new nil, :paragraph, :attributes => { 'foo' => 'bar' }
|
355
396
|
assert_equal 'bar', (node.attr 'foo')
|
@@ -377,6 +418,31 @@ content
|
|
377
418
|
assert_xpath '//a[@href="https://google.com"]', output, 1
|
378
419
|
end
|
379
420
|
|
421
|
+
test 'set_attribute should set attribute if key is not locked' do
|
422
|
+
doc = empty_document
|
423
|
+
assert !(doc.attr? 'foo')
|
424
|
+
res = doc.set_attribute 'foo', 'baz'
|
425
|
+
assert res
|
426
|
+
assert_equal 'baz', (doc.attr 'foo')
|
427
|
+
end
|
428
|
+
|
429
|
+
test 'set_attribute should not set key if key is locked' do
|
430
|
+
doc = empty_document :attributes => { 'foo' => 'bar' }
|
431
|
+
assert_equal 'bar', (doc.attr 'foo')
|
432
|
+
res = doc.set_attribute 'foo', 'baz'
|
433
|
+
assert !res
|
434
|
+
assert_equal 'bar', (doc.attr 'foo')
|
435
|
+
end
|
436
|
+
|
437
|
+
test 'set_attribute should update backend attributes' do
|
438
|
+
doc = empty_document :attributes => { 'backend' => 'html5@' }
|
439
|
+
assert_equal '', (doc.attr 'backend-html5')
|
440
|
+
res = doc.set_attribute 'backend', 'docbook5'
|
441
|
+
assert res
|
442
|
+
assert !(doc.attr? 'backend-html5')
|
443
|
+
assert_equal '', (doc.attr 'backend-docbook5')
|
444
|
+
end
|
445
|
+
|
380
446
|
test 'verify toc attribute matrix' do
|
381
447
|
expected_data = <<-EOS
|
382
448
|
#attributes |toc|toc-position|toc-placement|toc-class
|
@@ -399,7 +465,7 @@ toc toc-placement! | |content |macro |nil
|
|
399
465
|
|
400
466
|
expected.each do |expect|
|
401
467
|
raw_attrs, toc, toc_position, toc_placement, toc_class = expect
|
402
|
-
attrs = Hash[*
|
468
|
+
attrs = Hash[*raw_attrs.split.map {|e| e.include?('=') ? e.split('=', 2) : [e, ''] }.flatten]
|
403
469
|
doc = document_from_string '', :attributes => attrs
|
404
470
|
toc ? (assert doc.attr?('toc', toc)) : (assert !doc.attr?('toc'))
|
405
471
|
toc_position ? (assert doc.attr?('toc-position', toc_position)) : (assert !doc.attr?('toc-position'))
|
@@ -448,7 +514,7 @@ Yo, {myfrog}!
|
|
448
514
|
assert_xpath '(//p)[1][text()="Yo, Tanglefoot!"]', output, 1
|
449
515
|
end
|
450
516
|
|
451
|
-
test
|
517
|
+
test 'ignores lines with bad attributes if attribute-missing is drop-line' do
|
452
518
|
input = <<-EOS
|
453
519
|
:attribute-missing: drop-line
|
454
520
|
|
@@ -456,9 +522,10 @@ This is
|
|
456
522
|
blah blah {foobarbaz}
|
457
523
|
all there is.
|
458
524
|
EOS
|
459
|
-
|
460
|
-
|
461
|
-
|
525
|
+
output, warnings = redirect_streams {|_, err| [(render_embedded_string input), err.string] }
|
526
|
+
para = xmlnodes_at_css 'p', output, 1
|
527
|
+
refute_includes 'blah blah', para.content
|
528
|
+
assert_includes warnings, 'dropping line containing reference to missing attribute'
|
462
529
|
end
|
463
530
|
|
464
531
|
test "attribute value gets interpretted when rendering" do
|
@@ -476,9 +543,10 @@ Line 1: This line should appear in the output.
|
|
476
543
|
Line 2: Oh no, a {bogus-attribute}! This line should not appear in the output.
|
477
544
|
EOS
|
478
545
|
|
479
|
-
output = render_embedded_string input
|
546
|
+
output, warnings = redirect_streams {|_, err| [(render_embedded_string input), err.string] }
|
480
547
|
assert_match(/Line 1/, output)
|
481
548
|
refute_match(/Line 2/, output)
|
549
|
+
assert_includes warnings, 'dropping line containing reference to missing attribute'
|
482
550
|
end
|
483
551
|
|
484
552
|
test 'should not drop line with reference to missing attribute by default' do
|
@@ -512,7 +580,7 @@ Line 2: {set:a!}This line should not appear in the output.
|
|
512
580
|
:a:
|
513
581
|
|
514
582
|
Line 1: This line should appear in the output.
|
515
|
-
Line 2: {set:a!}This line should
|
583
|
+
Line 2: {set:a!}This line should appear in the output.
|
516
584
|
EOS
|
517
585
|
|
518
586
|
output = render_embedded_string input
|
@@ -748,7 +816,7 @@ of the attribute named foo in your document.
|
|
748
816
|
{set:foo!}
|
749
817
|
{foo}yes
|
750
818
|
EOS
|
751
|
-
output = render_embedded_string input
|
819
|
+
output = redirect_streams { render_embedded_string input }
|
752
820
|
assert_xpath '//p', output, 1
|
753
821
|
assert_xpath '//p/child::text()', output, 0
|
754
822
|
end
|
@@ -878,6 +946,34 @@ after: {counter:mycounter}
|
|
878
946
|
assert_xpath '//p[text()="before: 1 2 3"]', output, 1
|
879
947
|
assert_xpath '//p[text()="after: 1"]', output, 1
|
880
948
|
end
|
949
|
+
|
950
|
+
test 'nested document should use counter from parent document' do
|
951
|
+
input = <<-EOS
|
952
|
+
.Title for Foo
|
953
|
+
image::foo.jpg[]
|
954
|
+
|
955
|
+
[cols="2*a"]
|
956
|
+
|===
|
957
|
+
|
|
958
|
+
.Title for Bar
|
959
|
+
image::bar.jpg[]
|
960
|
+
|
961
|
+
|
|
962
|
+
.Title for Baz
|
963
|
+
image::baz.jpg[]
|
964
|
+
|===
|
965
|
+
|
966
|
+
.Title for Qux
|
967
|
+
image::qux.jpg[]
|
968
|
+
EOS
|
969
|
+
|
970
|
+
output = render_embedded_string input
|
971
|
+
assert_xpath '//div[@class="title"]', output, 4
|
972
|
+
assert_xpath '//div[@class="title"][text() = "Figure 1. Title for Foo"]', output, 1
|
973
|
+
assert_xpath '//div[@class="title"][text() = "Figure 2. Title for Bar"]', output, 1
|
974
|
+
assert_xpath '//div[@class="title"][text() = "Figure 3. Title for Baz"]', output, 1
|
975
|
+
assert_xpath '//div[@class="title"][text() = "Figure 4. Title for Qux"]', output, 1
|
976
|
+
end
|
881
977
|
end
|
882
978
|
|
883
979
|
context 'Block attributes' do
|
@@ -952,7 +1048,7 @@ content
|
|
952
1048
|
assert_xpath '//*[@class="title"]/strong[text()="title"]', output, 1
|
953
1049
|
end
|
954
1050
|
|
955
|
-
test 'attribute list may begin with space' do
|
1051
|
+
test 'attribute list may not begin with space' do
|
956
1052
|
input = <<-EOS
|
957
1053
|
[ quote]
|
958
1054
|
____
|
@@ -961,8 +1057,8 @@ ____
|
|
961
1057
|
EOS
|
962
1058
|
|
963
1059
|
doc = document_from_string input
|
964
|
-
|
965
|
-
assert_equal 'quote',
|
1060
|
+
b1 = doc.blocks.first
|
1061
|
+
assert_equal ['[ quote]'], b1.lines
|
966
1062
|
end
|
967
1063
|
|
968
1064
|
test 'attribute list may begin with comma' do
|
@@ -1125,7 +1221,8 @@ A normal paragraph
|
|
1125
1221
|
EOS
|
1126
1222
|
doc = document_from_string(input)
|
1127
1223
|
para = doc.blocks.first
|
1128
|
-
para.add_role 'role1'
|
1224
|
+
res = para.add_role 'role1'
|
1225
|
+
assert res
|
1129
1226
|
assert_equal 'role1', para.attributes['role']
|
1130
1227
|
assert para.has_role? 'role1'
|
1131
1228
|
end
|
@@ -1137,7 +1234,8 @@ A normal paragraph
|
|
1137
1234
|
EOS
|
1138
1235
|
doc = document_from_string(input)
|
1139
1236
|
para = doc.blocks.first
|
1140
|
-
para.add_role 'role2'
|
1237
|
+
res = para.add_role 'role2'
|
1238
|
+
assert res
|
1141
1239
|
assert_equal 'role1 role2', para.attributes['role']
|
1142
1240
|
assert para.has_role? 'role1'
|
1143
1241
|
assert para.has_role? 'role2'
|
@@ -1150,7 +1248,8 @@ A normal paragraph
|
|
1150
1248
|
EOS
|
1151
1249
|
doc = document_from_string(input)
|
1152
1250
|
para = doc.blocks.first
|
1153
|
-
para.add_role 'role1'
|
1251
|
+
res = para.add_role 'role1'
|
1252
|
+
refute res
|
1154
1253
|
assert_equal 'role1', para.attributes['role']
|
1155
1254
|
assert para.has_role? 'role1'
|
1156
1255
|
end
|
@@ -1162,12 +1261,27 @@ A normal paragraph
|
|
1162
1261
|
EOS
|
1163
1262
|
doc = document_from_string(input)
|
1164
1263
|
para = doc.blocks.first
|
1165
|
-
para.remove_role 'role1'
|
1264
|
+
res = para.remove_role 'role1'
|
1265
|
+
assert res
|
1166
1266
|
assert_equal 'role2', para.attributes['role']
|
1167
1267
|
assert para.has_role? 'role2'
|
1168
1268
|
assert !para.has_role?('role1')
|
1169
1269
|
end
|
1170
1270
|
|
1271
|
+
test 'roles are removed when last role is removed using remove_role' do
|
1272
|
+
input = <<-EOS
|
1273
|
+
[.role1]
|
1274
|
+
A normal paragraph
|
1275
|
+
EOS
|
1276
|
+
doc = document_from_string(input)
|
1277
|
+
para = doc.blocks.first
|
1278
|
+
res = para.remove_role 'role1'
|
1279
|
+
assert res
|
1280
|
+
refute para.role?
|
1281
|
+
assert_equal nil, para.attributes['role']
|
1282
|
+
refute para.has_role? 'role1'
|
1283
|
+
end
|
1284
|
+
|
1171
1285
|
test 'roles are not changed when a non-existent role is removed using remove_role' do
|
1172
1286
|
input = <<-EOS
|
1173
1287
|
[.role1]
|
@@ -1175,7 +1289,8 @@ A normal paragraph
|
|
1175
1289
|
EOS
|
1176
1290
|
doc = document_from_string(input)
|
1177
1291
|
para = doc.blocks.first
|
1178
|
-
para.remove_role 'role2'
|
1292
|
+
res = para.remove_role 'role2'
|
1293
|
+
refute res
|
1179
1294
|
assert_equal 'role1', para.attributes['role']
|
1180
1295
|
assert para.has_role? 'role1'
|
1181
1296
|
assert !para.has_role?('role2')
|
@@ -1187,7 +1302,8 @@ A normal paragraph
|
|
1187
1302
|
EOS
|
1188
1303
|
doc = document_from_string(input)
|
1189
1304
|
para = doc.blocks.first
|
1190
|
-
para.remove_role 'role1'
|
1305
|
+
res = para.remove_role 'role1'
|
1306
|
+
refute res
|
1191
1307
|
assert_equal nil, para.attributes['role']
|
1192
1308
|
assert !para.has_role?('role1')
|
1193
1309
|
end
|
@@ -1265,7 +1381,7 @@ paragraph
|
|
1265
1381
|
assert_equal 'coolio', subsec.id
|
1266
1382
|
end
|
1267
1383
|
|
1268
|
-
test "trailing block attributes
|
1384
|
+
test "trailing block attributes transfer to the following section" do
|
1269
1385
|
input = <<-EOS
|
1270
1386
|
[[one]]
|
1271
1387
|
|
data/test/blocks_test.rb
CHANGED
@@ -5,22 +5,39 @@ unless defined? ASCIIDOCTOR_PROJECT_DIR
|
|
5
5
|
end
|
6
6
|
|
7
7
|
context "Blocks" do
|
8
|
-
context '
|
9
|
-
test
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
context 'Layout Breaks' do
|
9
|
+
test 'horizontal rule' do
|
10
|
+
%w(''' '''' '''''').each do |line|
|
11
|
+
output = render_embedded_string line
|
12
|
+
assert_includes output, '<hr>'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
test '< 3 chars does not make horizontal rule' do
|
17
|
+
%w(' '').each do |line|
|
18
|
+
output = render_embedded_string line
|
19
|
+
refute_includes output, '<hr>'
|
20
|
+
assert_includes output, %(<p>#{line}</p>)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
test 'mixed chars does not make horizontal rule' do
|
25
|
+
[%q(''<), %q('''<), %q(' ' ')].each do |line|
|
26
|
+
output = render_embedded_string line
|
27
|
+
refute_includes output, '<hr>'
|
28
|
+
assert_includes output, %(<p>#{line.sub '<', '<'}</p>)
|
29
|
+
end
|
13
30
|
end
|
14
31
|
|
15
|
-
test
|
16
|
-
output =
|
17
|
-
assert_xpath '
|
18
|
-
assert_xpath '
|
19
|
-
assert_xpath '
|
32
|
+
test 'horizontal rule between blocks' do
|
33
|
+
output = render_embedded_string %(Block above\n\n'''\n\nBlock below)
|
34
|
+
assert_xpath '/hr', output, 1
|
35
|
+
assert_xpath '/hr/preceding-sibling::*', output, 1
|
36
|
+
assert_xpath '/hr/following-sibling::*', output, 1
|
20
37
|
end
|
21
38
|
|
22
|
-
test
|
23
|
-
output = render_embedded_string(
|
39
|
+
test 'page break' do
|
40
|
+
output = render_embedded_string %(page 1\n\n<<<\n\npage 2)
|
24
41
|
assert_xpath '/*[translate(@style, ";", "")="page-break-after: always"]', output, 1
|
25
42
|
assert_xpath '/*[translate(@style, ";", "")="page-break-after: always"]/preceding-sibling::div/p[text()="page 1"]', output, 1
|
26
43
|
assert_xpath '/*[translate(@style, ";", "")="page-break-after: always"]/following-sibling::div/p[text()="page 2"]', output, 1
|
@@ -254,7 +271,7 @@ ____
|
|
254
271
|
assert_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]/cite[text() = "Famous Book (1999)"]', output, 1
|
255
272
|
attribution = xmlnodes_at_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]', output, 1
|
256
273
|
author = attribution.children.first
|
257
|
-
assert_equal "#{
|
274
|
+
assert_equal "#{decode_char 8212} Famous Person", author.text.strip
|
258
275
|
end
|
259
276
|
|
260
277
|
test 'quote block with attribute and id and role shorthand' do
|
@@ -374,7 +391,7 @@ Some more inspiring words.
|
|
374
391
|
assert_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]/cite[text() = "Famous Source, Volume 1 (1999)"]', output, 1
|
375
392
|
attribution = xmlnodes_at_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]', output, 1
|
376
393
|
author = attribution.children.first
|
377
|
-
assert_equal "#{
|
394
|
+
assert_equal "#{decode_char 8212} Famous Person", author.text.strip
|
378
395
|
end
|
379
396
|
|
380
397
|
test 'quoted paragraph-style quote block with attribution' do
|
@@ -393,7 +410,7 @@ Some more inspiring words."
|
|
393
410
|
assert_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]/cite[text() = "Famous Source, Volume 1 (1999)"]', output, 1
|
394
411
|
attribution = xmlnodes_at_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]', output, 1
|
395
412
|
author = attribution.children.first
|
396
|
-
assert_equal "#{
|
413
|
+
assert_equal "#{decode_char 8212} Famous Person", author.text.strip
|
397
414
|
end
|
398
415
|
|
399
416
|
test 'single-line verse block without attribution' do
|
@@ -428,7 +445,7 @@ ____
|
|
428
445
|
assert_xpath '//*[@class = "verseblock"]/*[@class = "attribution"]/cite[text() = "Famous Poem"]', output, 1
|
429
446
|
attribution = xmlnodes_at_xpath '//*[@class = "verseblock"]/*[@class = "attribution"]', output, 1
|
430
447
|
author = attribution.children.first
|
431
|
-
assert_equal "#{
|
448
|
+
assert_equal "#{decode_char 8212} Famous Poet", author.text.strip
|
432
449
|
end
|
433
450
|
|
434
451
|
test 'multi-stanza verse block' do
|
@@ -475,7 +492,7 @@ ____
|
|
475
492
|
EOS
|
476
493
|
|
477
494
|
verse = block_from_string input
|
478
|
-
assert_equal Asciidoctor::Substitutors::
|
495
|
+
assert_equal Asciidoctor::Substitutors::NORMAL_SUBS, verse.subs
|
479
496
|
end
|
480
497
|
|
481
498
|
test 'should not recognize callouts in a verse' do
|
@@ -487,8 +504,9 @@ ____
|
|
487
504
|
<1> Not pointing to a callout
|
488
505
|
EOS
|
489
506
|
|
490
|
-
output = render_embedded_string input
|
507
|
+
output, warnings = redirect_streams {|_, err| [(render_embedded_string input), err.string] }
|
491
508
|
assert_xpath '//pre[text()="La la la <1>"]', output, 1
|
509
|
+
assert_includes warnings, 'line 5: no callouts refer to list item 1'
|
492
510
|
end
|
493
511
|
|
494
512
|
test 'should perform normal subs on a verse block' do
|
@@ -536,6 +554,8 @@ You futz with XML.
|
|
536
554
|
EOS
|
537
555
|
|
538
556
|
doc = document_from_string input
|
557
|
+
assert_equal 1, doc.blocks[0].number
|
558
|
+
assert_equal 2, doc.blocks[1].number
|
539
559
|
output = doc.render
|
540
560
|
assert_xpath '(//*[@class="exampleblock"])[1]/*[@class="title"][text()="Example 1. Writing Docs with AsciiDoc"]', output, 1
|
541
561
|
assert_xpath '(//*[@class="exampleblock"])[2]/*[@class="title"][text()="Example 2. Writing Docs with DocBook"]', output, 1
|
@@ -562,6 +582,8 @@ You futz with XML.
|
|
562
582
|
EOS
|
563
583
|
|
564
584
|
doc = document_from_string input
|
585
|
+
assert_equal 'A', doc.blocks[0].number
|
586
|
+
assert_equal 'B', doc.blocks[1].number
|
565
587
|
output = doc.render
|
566
588
|
assert_xpath '(//*[@class="exampleblock"])[1]/*[@class="title"][text()="Example A. Writing Docs with AsciiDoc"]', output, 1
|
567
589
|
assert_xpath '(//*[@class="exampleblock"])[2]/*[@class="title"][text()="Example B. Writing Docs with DocBook"]', output, 1
|
@@ -580,25 +602,12 @@ You just write.
|
|
580
602
|
EOS
|
581
603
|
|
582
604
|
doc = document_from_string input
|
605
|
+
assert_nil doc.blocks[0].number
|
583
606
|
output = doc.render
|
584
607
|
assert_xpath '(//*[@class="exampleblock"])[1]/*[@class="title"][text()="Look! Writing Docs with AsciiDoc"]', output, 1
|
585
608
|
assert !doc.attributes.has_key?('example-number')
|
586
609
|
end
|
587
610
|
|
588
|
-
test 'explicit caption is set on block even if block has no title' do
|
589
|
-
input = <<-EOS
|
590
|
-
[caption="Look!"]
|
591
|
-
====
|
592
|
-
Just write.
|
593
|
-
====
|
594
|
-
EOS
|
595
|
-
|
596
|
-
doc = document_from_string input
|
597
|
-
assert_equal 'Look!', doc.blocks.first.caption
|
598
|
-
output = doc.render
|
599
|
-
refute_match(/Look/, output)
|
600
|
-
end
|
601
|
-
|
602
611
|
test 'automatic caption can be turned off and on and modified' do
|
603
612
|
input = <<-EOS
|
604
613
|
.first example
|
@@ -802,7 +811,7 @@ source line 2\r
|
|
802
811
|
----
|
803
812
|
def names
|
804
813
|
|
805
|
-
@names.split
|
814
|
+
@names.split
|
806
815
|
|
807
816
|
end
|
808
817
|
----
|
@@ -811,7 +820,7 @@ source line 2\r
|
|
811
820
|
expected = <<-EOS
|
812
821
|
def names
|
813
822
|
|
814
|
-
@names.split
|
823
|
+
@names.split
|
815
824
|
|
816
825
|
end
|
817
826
|
EOS
|
@@ -829,7 +838,7 @@ end
|
|
829
838
|
----
|
830
839
|
def names
|
831
840
|
|
832
|
-
@names.split
|
841
|
+
@names.split
|
833
842
|
|
834
843
|
end
|
835
844
|
----
|
@@ -838,7 +847,7 @@ end
|
|
838
847
|
expected = <<-EOS
|
839
848
|
def names
|
840
849
|
|
841
|
-
@names.split
|
850
|
+
@names.split
|
842
851
|
|
843
852
|
end
|
844
853
|
EOS
|
@@ -856,7 +865,7 @@ end
|
|
856
865
|
----
|
857
866
|
def names
|
858
867
|
|
859
|
-
@names.split
|
868
|
+
@names.split
|
860
869
|
|
861
870
|
end
|
862
871
|
----
|
@@ -865,7 +874,7 @@ end
|
|
865
874
|
expected = <<-EOS
|
866
875
|
def names
|
867
876
|
|
868
|
-
@names.split
|
877
|
+
@names.split
|
869
878
|
|
870
879
|
end
|
871
880
|
EOS
|
@@ -885,7 +894,7 @@ end
|
|
885
894
|
----
|
886
895
|
def names
|
887
896
|
|
888
|
-
@names.split
|
897
|
+
@names.split
|
889
898
|
|
890
899
|
end
|
891
900
|
----
|
@@ -894,7 +903,7 @@ end
|
|
894
903
|
expected = <<-EOS
|
895
904
|
def names
|
896
905
|
|
897
|
-
@names.split
|
906
|
+
@names.split
|
898
907
|
|
899
908
|
end
|
900
909
|
EOS
|
@@ -914,7 +923,7 @@ end
|
|
914
923
|
----
|
915
924
|
def names
|
916
925
|
|
917
|
-
@names.split
|
926
|
+
@names.split
|
918
927
|
|
919
928
|
end
|
920
929
|
----
|
@@ -923,7 +932,7 @@ end
|
|
923
932
|
expected = <<-EOS
|
924
933
|
def names
|
925
934
|
|
926
|
-
@names.split
|
935
|
+
@names.split
|
927
936
|
|
928
937
|
end
|
929
938
|
EOS
|
@@ -1212,7 +1221,7 @@ line below
|
|
1212
1221
|
|
1213
1222
|
output = render_embedded_string input
|
1214
1223
|
assert_css '.stemblock', output, 1
|
1215
|
-
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
|
1224
|
+
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
|
1216
1225
|
assert_equal '\[\sqrt{3x-1}+(1+x)^2 < y\]', nodes.first.to_s.strip
|
1217
1226
|
end
|
1218
1227
|
|
@@ -1226,7 +1235,7 @@ line below
|
|
1226
1235
|
|
1227
1236
|
output = render_embedded_string input
|
1228
1237
|
assert_css '.stemblock', output, 1
|
1229
|
-
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
|
1238
|
+
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
|
1230
1239
|
assert_equal '\[\sqrt{3x-1}+(1+x)^2 < y\]', nodes.first.to_s.strip
|
1231
1240
|
end
|
1232
1241
|
|
@@ -1259,7 +1268,7 @@ sqrt(3x-1)+(1+x)^2 < y
|
|
1259
1268
|
|
1260
1269
|
output = render_embedded_string input
|
1261
1270
|
assert_css '.stemblock', output, 1
|
1262
|
-
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
|
1271
|
+
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
|
1263
1272
|
assert_equal '\$sqrt(3x-1)+(1+x)^2 < y\$', nodes.first.to_s.strip
|
1264
1273
|
end
|
1265
1274
|
|
@@ -1273,7 +1282,7 @@ sqrt(3x-1)+(1+x)^2 < y
|
|
1273
1282
|
|
1274
1283
|
output = render_embedded_string input
|
1275
1284
|
assert_css '.stemblock', output, 1
|
1276
|
-
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
|
1285
|
+
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
|
1277
1286
|
assert_equal '\$sqrt(3x-1)+(1+x)^2 < y\$', nodes.first.to_s.strip
|
1278
1287
|
end
|
1279
1288
|
|
@@ -1342,7 +1351,7 @@ sqrt(3x-1)+(1+x)^2 < y
|
|
1342
1351
|
].each do |attributes|
|
1343
1352
|
output = render_embedded_string input, :attributes => attributes
|
1344
1353
|
assert_css '.stemblock', output, 1
|
1345
|
-
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
|
1354
|
+
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
|
1346
1355
|
assert_equal '\$sqrt(3x-1)+(1+x)^2 < y\$', nodes.first.to_s.strip
|
1347
1356
|
end
|
1348
1357
|
end
|
@@ -1357,7 +1366,7 @@ sqrt(3x-1)+(1+x)^2 < y
|
|
1357
1366
|
|
1358
1367
|
output = render_embedded_string input, :attributes => {'stem' => 'latexmath'}
|
1359
1368
|
assert_css '.stemblock', output, 1
|
1360
|
-
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
|
1369
|
+
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output
|
1361
1370
|
assert_equal '\[\sqrt{3x-1}+(1+x)^2 < y\]', nodes.first.to_s.strip
|
1362
1371
|
end
|
1363
1372
|
end
|
@@ -1399,6 +1408,7 @@ section paragraph
|
|
1399
1408
|
|
1400
1409
|
test 'block title above document title gets carried over to first block in first section if no preamble' do
|
1401
1410
|
input = <<-EOS
|
1411
|
+
:doctype: book
|
1402
1412
|
.Block title
|
1403
1413
|
= Document Title
|
1404
1414
|
|
@@ -1406,7 +1416,10 @@ section paragraph
|
|
1406
1416
|
|
1407
1417
|
paragraph
|
1408
1418
|
EOS
|
1409
|
-
|
1419
|
+
doc = document_from_string input
|
1420
|
+
# NOTE block title demotes document title to level-0 section
|
1421
|
+
refute doc.header?
|
1422
|
+
output = doc.convert
|
1410
1423
|
assert_xpath '//*[@class="sect1"]//*[@class="paragraph"]/*[@class="title"][text() = "Block title"]', output, 1
|
1411
1424
|
end
|
1412
1425
|
|
@@ -1548,18 +1561,39 @@ image::circle.svg[Tiger,100]
|
|
1548
1561
|
image::no-such-image.svg[Alt Text]
|
1549
1562
|
EOS
|
1550
1563
|
|
1551
|
-
output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER
|
1564
|
+
output, warnings = redirect_streams {|_, err| [(render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER), err.string] }
|
1552
1565
|
assert_xpath '//span[@class="alt"][text()="Alt Text"]', output, 1
|
1566
|
+
assert_includes warnings, 'SVG does not exist or cannot be read'
|
1553
1567
|
end
|
1554
1568
|
|
1555
|
-
test 'can render block image with alt text defined in macro containing
|
1569
|
+
test 'can render block image with alt text defined in macro containing square bracket' do
|
1556
1570
|
input = <<-EOS
|
1557
|
-
image::images/tiger.png[A [Bengal
|
1571
|
+
image::images/tiger.png[A [Bengal] Tiger]
|
1558
1572
|
EOS
|
1559
1573
|
|
1560
1574
|
output = render_string input
|
1561
1575
|
img = xmlnodes_at_xpath '//img', output, 1
|
1562
|
-
assert_equal 'A [Bengal] Tiger', img.attr('alt')
|
1576
|
+
assert_equal 'A [Bengal] Tiger', img.attr('alt')
|
1577
|
+
end
|
1578
|
+
|
1579
|
+
test 'can render block image with target containing spaces' do
|
1580
|
+
input = <<-EOS
|
1581
|
+
image::images/big tiger.png[A Big Tiger]
|
1582
|
+
EOS
|
1583
|
+
|
1584
|
+
output = render_string input
|
1585
|
+
img = xmlnodes_at_xpath '//img', output, 1
|
1586
|
+
assert_equal 'images/big%20tiger.png', img.attr('src')
|
1587
|
+
assert_equal 'A Big Tiger', img.attr('alt')
|
1588
|
+
end
|
1589
|
+
|
1590
|
+
test 'should not recognize block image if target has leading or trailing spaces' do
|
1591
|
+
[' tiger.png', 'tiger.png '].each do |target|
|
1592
|
+
input = %(image::#{target}[Tiger])
|
1593
|
+
|
1594
|
+
output = render_embedded_string input
|
1595
|
+
assert_xpath '//img', output, 0
|
1596
|
+
end
|
1563
1597
|
end
|
1564
1598
|
|
1565
1599
|
test 'can render block image with alt text defined in block attribute above macro' do
|
@@ -1582,31 +1616,52 @@ image::images/tiger.png[Tiger]
|
|
1582
1616
|
assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
|
1583
1617
|
end
|
1584
1618
|
|
1585
|
-
test 'alt text
|
1619
|
+
test 'should substitute attribute references in alt text defined in image block macro' do
|
1586
1620
|
input = <<-EOS
|
1587
|
-
|
1588
|
-
EOS
|
1621
|
+
:alt-text: Tiger
|
1589
1622
|
|
1623
|
+
image::images/tiger.png[{alt-text}]
|
1624
|
+
EOS
|
1590
1625
|
output = render_embedded_string input
|
1591
|
-
|
1626
|
+
assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
|
1592
1627
|
end
|
1593
1628
|
|
1594
|
-
test '
|
1629
|
+
test 'style attribute is dropped from image macro' do
|
1595
1630
|
input = <<-EOS
|
1596
|
-
|
1631
|
+
[style=value]
|
1632
|
+
image::images/tiger.png[Tiger]
|
1597
1633
|
EOS
|
1598
1634
|
|
1599
|
-
|
1600
|
-
|
1635
|
+
doc = document_from_string input
|
1636
|
+
img = doc.blocks[0]
|
1637
|
+
refute(img.attributes.key? 'style')
|
1638
|
+
assert_nil img.style
|
1639
|
+
end
|
1640
|
+
|
1641
|
+
test 'should apply specialcharacters and replacement substitutions to alt text' do
|
1642
|
+
input = 'A tiger\'s "roar" is < a bear\'s "growl"'
|
1643
|
+
expected = 'A tiger’s "roar" is < a bear’s "growl"'
|
1644
|
+
result = render_embedded_string %(image::images/tiger-roar.png[#{input}])
|
1645
|
+
assert_includes result, %(alt="#{expected}")
|
1601
1646
|
end
|
1602
1647
|
|
1603
|
-
test
|
1648
|
+
test 'should not encode double quotes in alt text when converting to DocBook' do
|
1649
|
+
input = 'Select "File > Open"'
|
1650
|
+
expected = 'Select "File > Open"'
|
1651
|
+
result = render_embedded_string %(image::images/open.png[#{input}]), :backend => :docbook
|
1652
|
+
assert_includes result, %(<phrase>#{expected}</phrase>)
|
1653
|
+
end
|
1654
|
+
|
1655
|
+
test 'should auto-generate alt text for block image if alt text is not specified' do
|
1604
1656
|
input = <<-EOS
|
1605
|
-
image::images/
|
1657
|
+
image::images/lions-and-tigers.png[]
|
1606
1658
|
EOS
|
1607
1659
|
|
1608
|
-
|
1609
|
-
|
1660
|
+
image = block_from_string input
|
1661
|
+
assert_equal 'lions and tigers', (image.attr 'alt')
|
1662
|
+
assert_equal 'lions and tigers', (image.attr 'default-alt')
|
1663
|
+
output = image.convert
|
1664
|
+
assert_xpath '/*[@class="imageblock"]//img[@src="images/lions-and-tigers.png"][@alt="lions and tigers"]', output, 1
|
1610
1665
|
end
|
1611
1666
|
|
1612
1667
|
test "can render block image with alt text and height and width" do
|
@@ -1627,13 +1682,32 @@ image::images/tiger.png[Tiger, link='http://en.wikipedia.org/wiki/Tiger']
|
|
1627
1682
|
assert_xpath '/*[@class="imageblock"]//a[@class="image"][@href="http://en.wikipedia.org/wiki/Tiger"]/img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
|
1628
1683
|
end
|
1629
1684
|
|
1630
|
-
test
|
1685
|
+
test 'adds rel=noopener attribute to block image with link that targets _blank window' do
|
1686
|
+
input = <<-EOS
|
1687
|
+
image::images/tiger.png[Tiger,link=http://en.wikipedia.org/wiki/Tiger,window=_blank]
|
1688
|
+
EOS
|
1689
|
+
|
1690
|
+
output = render_embedded_string input
|
1691
|
+
assert_xpath '/*[@class="imageblock"]//a[@class="image"][@href="http://en.wikipedia.org/wiki/Tiger"][@target="_blank"][@rel="noopener"]/img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
|
1692
|
+
end
|
1693
|
+
|
1694
|
+
test 'adds rel=noopener attribute to block image with link that targets name window when the noopener option is set' do
|
1695
|
+
input = <<-EOS
|
1696
|
+
image::images/tiger.png[Tiger,link=http://en.wikipedia.org/wiki/Tiger,window=name,opts=noopener]
|
1697
|
+
EOS
|
1698
|
+
|
1699
|
+
output = render_embedded_string input
|
1700
|
+
assert_xpath '/*[@class="imageblock"]//a[@class="image"][@href="http://en.wikipedia.org/wiki/Tiger"][@target="name"][@rel="noopener"]/img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
|
1701
|
+
end
|
1702
|
+
|
1703
|
+
test 'can render block image with caption' do
|
1631
1704
|
input = <<-EOS
|
1632
1705
|
.The AsciiDoc Tiger
|
1633
1706
|
image::images/tiger.png[Tiger]
|
1634
1707
|
EOS
|
1635
1708
|
|
1636
1709
|
doc = document_from_string input
|
1710
|
+
assert_equal 1, doc.blocks[0].number
|
1637
1711
|
output = doc.render
|
1638
1712
|
assert_xpath '//*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
|
1639
1713
|
assert_xpath '//*[@class="imageblock"]/*[@class="title"][text() = "Figure 1. The AsciiDoc Tiger"]', output, 1
|
@@ -1648,6 +1722,7 @@ image::images/tiger.png[Tiger]
|
|
1648
1722
|
EOS
|
1649
1723
|
|
1650
1724
|
doc = document_from_string input
|
1725
|
+
assert_nil doc.blocks[0].number
|
1651
1726
|
output = doc.render
|
1652
1727
|
assert_xpath '//*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
|
1653
1728
|
assert_xpath '//*[@class="imageblock"]/*[@class="title"][text() = "Voila! The AsciiDoc Tiger"]', output, 1
|
@@ -1656,7 +1731,7 @@ image::images/tiger.png[Tiger]
|
|
1656
1731
|
|
1657
1732
|
test 'can align image in DocBook backend' do
|
1658
1733
|
input = <<-EOS
|
1659
|
-
image::images/sunset.jpg[Sunset,
|
1734
|
+
image::images/sunset.jpg[Sunset,align=right]
|
1660
1735
|
EOS
|
1661
1736
|
|
1662
1737
|
output = render_embedded_string input, :backend => :docbook
|
@@ -1664,36 +1739,54 @@ image::images/sunset.jpg[Sunset, align="right"]
|
|
1664
1739
|
assert_xpath '//imagedata[@align="right"]', output, 1
|
1665
1740
|
end
|
1666
1741
|
|
1742
|
+
test 'should set content width and depth in DocBook backend if no scaling' do
|
1743
|
+
input = <<-EOS
|
1744
|
+
image::images/sunset.jpg[Sunset,500,332]
|
1745
|
+
EOS
|
1746
|
+
|
1747
|
+
output = render_embedded_string input, :backend => :docbook
|
1748
|
+
assert_xpath '//imagedata', output, 1
|
1749
|
+
assert_xpath '//imagedata[@contentwidth="500"]', output, 1
|
1750
|
+
assert_xpath '//imagedata[@contentdepth="332"]', output, 1
|
1751
|
+
assert_xpath '//imagedata[@width]', output, 0
|
1752
|
+
assert_xpath '//imagedata[@depth]', output, 0
|
1753
|
+
end
|
1754
|
+
|
1667
1755
|
test 'can scale image in DocBook backend' do
|
1668
1756
|
input = <<-EOS
|
1669
|
-
image::images/sunset.jpg[Sunset,
|
1757
|
+
image::images/sunset.jpg[Sunset,500,332,scale=200]
|
1670
1758
|
EOS
|
1671
1759
|
|
1672
1760
|
output = render_embedded_string input, :backend => :docbook
|
1673
1761
|
assert_xpath '//imagedata', output, 1
|
1674
1762
|
assert_xpath '//imagedata[@scale="200"]', output, 1
|
1763
|
+
assert_xpath '//imagedata[@width]', output, 0
|
1764
|
+
assert_xpath '//imagedata[@depth]', output, 0
|
1765
|
+
assert_xpath '//imagedata[@contentwidth]', output, 0
|
1766
|
+
assert_xpath '//imagedata[@contentdepth]', output, 0
|
1675
1767
|
end
|
1676
1768
|
|
1677
|
-
test '
|
1769
|
+
test 'scale image width in DocBook backend' do
|
1678
1770
|
input = <<-EOS
|
1679
|
-
image::images/sunset.jpg[Sunset,
|
1771
|
+
image::images/sunset.jpg[Sunset,500,332,scaledwidth=25%]
|
1680
1772
|
EOS
|
1681
1773
|
|
1682
1774
|
output = render_embedded_string input, :backend => :docbook
|
1683
1775
|
assert_xpath '//imagedata', output, 1
|
1684
1776
|
assert_xpath '//imagedata[@width="25%"]', output, 1
|
1685
|
-
assert_xpath '//imagedata[@
|
1777
|
+
assert_xpath '//imagedata[@depth]', output, 0
|
1778
|
+
assert_xpath '//imagedata[@contentwidth]', output, 0
|
1779
|
+
assert_xpath '//imagedata[@contentdepth]', output, 0
|
1686
1780
|
end
|
1687
1781
|
|
1688
1782
|
test 'adds % to scaled width if no units given in DocBook backend ' do
|
1689
1783
|
input = <<-EOS
|
1690
|
-
image::images/sunset.jpg[Sunset,
|
1784
|
+
image::images/sunset.jpg[Sunset,scaledwidth=25]
|
1691
1785
|
EOS
|
1692
1786
|
|
1693
1787
|
output = render_embedded_string input, :backend => :docbook
|
1694
1788
|
assert_xpath '//imagedata', output, 1
|
1695
1789
|
assert_xpath '//imagedata[@width="25%"]', output, 1
|
1696
|
-
assert_xpath '//imagedata[@scalefit="1"]', output, 1
|
1697
1790
|
end
|
1698
1791
|
|
1699
1792
|
test 'keeps line unprocessed if image target is missing attribute reference and attribute-missing is skip' do
|
@@ -1703,8 +1796,9 @@ image::images/sunset.jpg[Sunset, scaledwidth="25"]
|
|
1703
1796
|
image::{bogus}[]
|
1704
1797
|
EOS
|
1705
1798
|
|
1706
|
-
output = render_embedded_string input
|
1799
|
+
output, warnings = redirect_streams {|_, err| [(render_embedded_string input), err.string] }
|
1707
1800
|
assert output.include?('image::{bogus}[]')
|
1801
|
+
assert_includes warnings, 'dropping line containing reference to missing attribute'
|
1708
1802
|
end
|
1709
1803
|
|
1710
1804
|
test 'drops line if image target is missing attribute reference and attribute-missing is drop' do
|
@@ -1714,8 +1808,9 @@ image::{bogus}[]
|
|
1714
1808
|
image::{bogus}[]
|
1715
1809
|
EOS
|
1716
1810
|
|
1717
|
-
output = render_embedded_string input
|
1811
|
+
output, warnings = redirect_streams {|_, err| [(render_embedded_string input), err.string] }
|
1718
1812
|
assert output.strip.empty?
|
1813
|
+
assert_includes warnings, 'dropping line containing reference to missing attribute'
|
1719
1814
|
end
|
1720
1815
|
|
1721
1816
|
test 'drops line if image target is missing attribute reference and attribute-missing is drop-line' do
|
@@ -1725,8 +1820,9 @@ image::{bogus}[]
|
|
1725
1820
|
image::{bogus}[]
|
1726
1821
|
EOS
|
1727
1822
|
|
1728
|
-
output = render_embedded_string input
|
1823
|
+
output, warnings = redirect_streams {|_, err| [(render_embedded_string input), err.string] }
|
1729
1824
|
assert output.strip.empty?
|
1825
|
+
assert_includes warnings, 'dropping line containing reference to missing attribute'
|
1730
1826
|
end
|
1731
1827
|
|
1732
1828
|
test 'dropped image does not break processing of following section and attribute-missing is drop-line' do
|
@@ -1738,10 +1834,11 @@ image::{bogus}[]
|
|
1738
1834
|
== Section Title
|
1739
1835
|
EOS
|
1740
1836
|
|
1741
|
-
output = render_embedded_string input
|
1837
|
+
output, warnings = redirect_streams {|_, err| [(render_embedded_string input), err.string] }
|
1742
1838
|
assert_css 'img', output, 0
|
1743
1839
|
assert_css 'h2', output, 1
|
1744
1840
|
assert !output.include?('== Section Title')
|
1841
|
+
assert_includes warnings, 'dropping line containing reference to missing attribute'
|
1745
1842
|
end
|
1746
1843
|
|
1747
1844
|
test 'should pass through image that references uri' do
|
@@ -1755,6 +1852,15 @@ image::http://asciidoc.org/images/tiger.png[Tiger]
|
|
1755
1852
|
assert_xpath '/*[@class="imageblock"]//img[@src="http://asciidoc.org/images/tiger.png"][@alt="Tiger"]', output, 1
|
1756
1853
|
end
|
1757
1854
|
|
1855
|
+
test 'should encode spaces in image target if value is a URI' do
|
1856
|
+
input = <<-EOS
|
1857
|
+
image::http://example.org/svg?digraph=digraph G { a -> b; }[diagram]
|
1858
|
+
EOS
|
1859
|
+
|
1860
|
+
output = render_embedded_string input
|
1861
|
+
assert_xpath %(/*[@class="imageblock"]//img[@src="http://example.org/svg?digraph=digraph%20G%20{%20a%20-#{decode_char 62}%20b;%20}"]), output, 1
|
1862
|
+
end
|
1863
|
+
|
1758
1864
|
test 'can resolve image relative to imagesdir' do
|
1759
1865
|
input = <<-EOS
|
1760
1866
|
:imagesdir: images
|
@@ -1780,6 +1886,21 @@ image::dot.gif[Dot]
|
|
1780
1886
|
assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
|
1781
1887
|
end
|
1782
1888
|
|
1889
|
+
test 'embeds empty base64-encoded data uri for unreadable image when data-uri attribute is set' do
|
1890
|
+
input = <<-EOS
|
1891
|
+
:data-uri:
|
1892
|
+
:imagesdir: fixtures
|
1893
|
+
|
1894
|
+
image::unreadable.gif[Dot]
|
1895
|
+
EOS
|
1896
|
+
|
1897
|
+
doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)}
|
1898
|
+
assert_equal 'fixtures', doc.attributes['imagesdir']
|
1899
|
+
output, warnings = redirect_streams {|_, err| [doc.render, err.string] }
|
1900
|
+
assert_xpath '//img[@src="data:image/gif;base64,"]', output, 1
|
1901
|
+
assert_includes warnings, 'image to embed not found or not readable'
|
1902
|
+
end
|
1903
|
+
|
1783
1904
|
test 'embeds base64-encoded data uri for remote image when data-uri attribute is set' do
|
1784
1905
|
input = <<-EOS
|
1785
1906
|
:data-uri:
|
@@ -1817,11 +1938,16 @@ image::dot.gif[Dot]
|
|
1817
1938
|
image::#{image_uri}[Missing image]
|
1818
1939
|
EOS
|
1819
1940
|
|
1820
|
-
output =
|
1821
|
-
|
1941
|
+
output = warnings = nil
|
1942
|
+
redirect_streams do |_, err|
|
1943
|
+
output = using_test_webserver do
|
1944
|
+
render_embedded_string input, :safe => :safe, :attributes => {'allow-uri-read' => ''}
|
1945
|
+
end
|
1946
|
+
warnings = err.string
|
1822
1947
|
end
|
1823
1948
|
|
1824
1949
|
assert_xpath %(/*[@class="imageblock"]//img[@src="#{image_uri}"][@alt="Missing image"]), output, 1
|
1950
|
+
assert_includes warnings, 'could not retrieve image data from URI'
|
1825
1951
|
end
|
1826
1952
|
|
1827
1953
|
test 'uses remote image uri when data-uri attribute is set and allow-uri-read is not set' do
|
@@ -1859,7 +1985,6 @@ image::data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=[Do
|
|
1859
1985
|
assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
|
1860
1986
|
end
|
1861
1987
|
|
1862
|
-
# this test will cause a warning to be printed to the console (until we have a message facility)
|
1863
1988
|
test 'cleans reference to ancestor directories in imagesdir before reading image if safe mode level is at least SAFE' do
|
1864
1989
|
input = <<-EOS
|
1865
1990
|
:data-uri:
|
@@ -1870,10 +1995,11 @@ image::dot.gif[Dot]
|
|
1870
1995
|
|
1871
1996
|
doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)}
|
1872
1997
|
assert_equal '../..//fixtures/./../../fixtures', doc.attributes['imagesdir']
|
1873
|
-
output = doc.render
|
1998
|
+
output, warnings = redirect_streams {|_, err| [doc.render, err.string] }
|
1874
1999
|
# image target resolves to fixtures/dot.gif relative to docdir (which is explicitly set to the directory of this file)
|
1875
2000
|
# the reference cannot fall outside of the document directory in safe mode
|
1876
2001
|
assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
|
2002
|
+
assert_includes warnings, 'image has illegal reference to ancestor of jail'
|
1877
2003
|
end
|
1878
2004
|
|
1879
2005
|
test 'cleans reference to ancestor directories in target before reading image if safe mode level is at least SAFE' do
|
@@ -1886,10 +2012,11 @@ image::../..//fixtures/./../../fixtures/dot.gif[Dot]
|
|
1886
2012
|
|
1887
2013
|
doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)}
|
1888
2014
|
assert_equal './', doc.attributes['imagesdir']
|
1889
|
-
output = doc.render
|
2015
|
+
output, warnings = redirect_streams {|_, err| [doc.render, err.string] }
|
1890
2016
|
# image target resolves to fixtures/dot.gif relative to docdir (which is explicitly set to the directory of this file)
|
1891
2017
|
# the reference cannot fall outside of the document directory in safe mode
|
1892
2018
|
assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
|
2019
|
+
assert_includes warnings, 'image has illegal reference to ancestor of jail'
|
1893
2020
|
end
|
1894
2021
|
end
|
1895
2022
|
|
@@ -1919,7 +2046,7 @@ video::cats-vs-dogs.avi[cats-and-dogs.png, 200, 300]
|
|
1919
2046
|
|
1920
2047
|
test 'video macro should honor all options' do
|
1921
2048
|
input = <<-EOS
|
1922
|
-
video::cats-vs-dogs.avi[options="autoplay,nocontrols,loop"]
|
2049
|
+
video::cats-vs-dogs.avi[options="autoplay,nocontrols,loop",preload="metadata"]
|
1923
2050
|
EOS
|
1924
2051
|
|
1925
2052
|
output = render_embedded_string input
|
@@ -1927,6 +2054,7 @@ video::cats-vs-dogs.avi[options="autoplay,nocontrols,loop"]
|
|
1927
2054
|
assert_css 'video[autoplay]', output, 1
|
1928
2055
|
assert_css 'video:not([controls])', output, 1
|
1929
2056
|
assert_css 'video[loop]', output, 1
|
2057
|
+
assert_css 'video[preload=metadata]', output, 1
|
1930
2058
|
end
|
1931
2059
|
|
1932
2060
|
test 'video macro should add time range anchor with start time if start attribute is set' do
|
@@ -2067,6 +2195,17 @@ audio::podcast.mp3[options="autoplay,nocontrols,loop"]
|
|
2067
2195
|
assert_css 'audio:not([controls])', output, 1
|
2068
2196
|
assert_css 'audio[loop]', output, 1
|
2069
2197
|
end
|
2198
|
+
|
2199
|
+
test 'audio macro should support start and end time' do
|
2200
|
+
input = <<-EOS
|
2201
|
+
audio::podcast.mp3[start=1,end=2]
|
2202
|
+
EOS
|
2203
|
+
|
2204
|
+
output = render_embedded_string input
|
2205
|
+
assert_css 'audio', output, 1
|
2206
|
+
assert_css 'audio[controls]', output, 1
|
2207
|
+
assert_css 'audio[src="podcast.mp3#t=1,2"]', output, 1
|
2208
|
+
end
|
2070
2209
|
end
|
2071
2210
|
|
2072
2211
|
context 'Admonition icons' do
|
@@ -2149,8 +2288,11 @@ You can use icons for admonitions by setting the 'icons' attribute.
|
|
2149
2288
|
You can use icons for admonitions by setting the 'icons' attribute.
|
2150
2289
|
EOS
|
2151
2290
|
|
2152
|
-
output =
|
2291
|
+
output, warnings = redirect_streams do |_, err|
|
2292
|
+
[(render_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)}), err.string]
|
2293
|
+
end
|
2153
2294
|
assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Tip"]', output, 1
|
2295
|
+
assert_includes warnings, 'image has illegal reference to ancestor of jail'
|
2154
2296
|
end
|
2155
2297
|
|
2156
2298
|
test 'should import Font Awesome and use font-based icons when value of icons attribute is font' do
|
@@ -2194,7 +2336,7 @@ puts "AsciiDoc, FTW!"
|
|
2194
2336
|
|
2195
2337
|
output = render_string input, :safe => Asciidoctor::SafeMode::SAFE
|
2196
2338
|
assert_css 'html > head > link[rel="stylesheet"][href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css"]', output, 1
|
2197
|
-
assert_css 'html > body > script[src="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/
|
2339
|
+
assert_css 'html > body > script[src="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"]', output, 1
|
2198
2340
|
end
|
2199
2341
|
|
2200
2342
|
test 'should use no uri scheme for assets when asset-uri-scheme is blank' do
|
@@ -2211,7 +2353,7 @@ puts "AsciiDoc, FTW!"
|
|
2211
2353
|
|
2212
2354
|
output = render_string input, :safe => Asciidoctor::SafeMode::SAFE
|
2213
2355
|
assert_css 'html > head > link[rel="stylesheet"][href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css"]', output, 1
|
2214
|
-
assert_css 'html > body > script[src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/
|
2356
|
+
assert_css 'html > body > script[src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"]', output, 1
|
2215
2357
|
end
|
2216
2358
|
end
|
2217
2359
|
|
@@ -2227,8 +2369,8 @@ image::asciidoctor.png[Asciidoctor]
|
|
2227
2369
|
assert doc.safe >= Asciidoctor::SafeMode::SAFE
|
2228
2370
|
|
2229
2371
|
assert_equal File.join(basedir, 'images'), block.normalize_asset_path('images')
|
2230
|
-
assert_equal File.join(basedir, 'etc/images'), block.normalize_asset_path("#{disk_root}etc/images")
|
2231
|
-
assert_equal File.join(basedir, 'images'), block.normalize_asset_path('../../images')
|
2372
|
+
assert_equal File.join(basedir, 'etc/images'), redirect_streams { block.normalize_asset_path("#{disk_root}etc/images") }
|
2373
|
+
assert_equal File.join(basedir, 'images'), redirect_streams { block.normalize_asset_path('../../images') }
|
2232
2374
|
end
|
2233
2375
|
|
2234
2376
|
test 'does not restrict access to ancestor directories when safe mode is disabled' do
|
@@ -2327,6 +2469,46 @@ html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table)
|
|
2327
2469
|
assert_match(/\.CodeRay *\{/, output)
|
2328
2470
|
end
|
2329
2471
|
|
2472
|
+
test 'should number lines if third positional attribute is set' do
|
2473
|
+
input = <<-EOS
|
2474
|
+
:source-highlighter: coderay
|
2475
|
+
|
2476
|
+
[source,ruby,linenums]
|
2477
|
+
----
|
2478
|
+
puts 'Hello, World!'
|
2479
|
+
----
|
2480
|
+
EOS
|
2481
|
+
output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SAFE
|
2482
|
+
assert_xpath '//td[@class="line-numbers"]', output, 1
|
2483
|
+
end
|
2484
|
+
|
2485
|
+
test 'should number lines if linenums option is set on source block' do
|
2486
|
+
input = <<-EOS
|
2487
|
+
:source-highlighter: coderay
|
2488
|
+
|
2489
|
+
[source%linenums,ruby]
|
2490
|
+
----
|
2491
|
+
puts 'Hello, World!'
|
2492
|
+
----
|
2493
|
+
EOS
|
2494
|
+
output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SAFE
|
2495
|
+
assert_xpath '//td[@class="line-numbers"]', output, 1
|
2496
|
+
end
|
2497
|
+
|
2498
|
+
test 'should number lines of source block if source-linenums-option document attribute is set' do
|
2499
|
+
input = <<-EOS
|
2500
|
+
:source-highlighter: coderay
|
2501
|
+
:source-linenums-option:
|
2502
|
+
|
2503
|
+
[source,ruby]
|
2504
|
+
----
|
2505
|
+
puts 'Hello, World!'
|
2506
|
+
----
|
2507
|
+
EOS
|
2508
|
+
output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SAFE
|
2509
|
+
assert_xpath '//td[@class="line-numbers"]', output, 1
|
2510
|
+
end
|
2511
|
+
|
2330
2512
|
test 'should read source language from source-language document attribute if not specified on source block' do
|
2331
2513
|
input = <<-EOS
|
2332
2514
|
:source-highlighter: coderay
|
@@ -2414,6 +2596,43 @@ exit 0 # <5><6>
|
|
2414
2596
|
assert_match(/exit.* <b class="conum">\(5\)<\/b> <b class="conum">\(6\)<\/b><\/pre>/, output)
|
2415
2597
|
end
|
2416
2598
|
|
2599
|
+
test 'should preserve space before callout on final line' do
|
2600
|
+
inputs = []
|
2601
|
+
|
2602
|
+
inputs << <<-EOS
|
2603
|
+
[source,yaml]
|
2604
|
+
----
|
2605
|
+
a: 'a'
|
2606
|
+
key: 'value' #<1>
|
2607
|
+
----
|
2608
|
+
<1> key-value pair
|
2609
|
+
EOS
|
2610
|
+
|
2611
|
+
inputs << <<-EOS
|
2612
|
+
[source,ruby]
|
2613
|
+
----
|
2614
|
+
puts 'hi'
|
2615
|
+
puts 'value' #<1>
|
2616
|
+
----
|
2617
|
+
<1> print to stdout
|
2618
|
+
EOS
|
2619
|
+
|
2620
|
+
inputs << <<-EOS
|
2621
|
+
[source,python]
|
2622
|
+
----
|
2623
|
+
print 'hi'
|
2624
|
+
print 'value' #<1>
|
2625
|
+
----
|
2626
|
+
<1> print to stdout
|
2627
|
+
EOS
|
2628
|
+
|
2629
|
+
inputs.each do |input|
|
2630
|
+
output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => { 'source-highlighter' => 'coderay' }
|
2631
|
+
output = output.gsub(/<\/?span.*?>/, '')
|
2632
|
+
assert_includes output, '\'value\' <b class="conum">(1)</b>'
|
2633
|
+
end
|
2634
|
+
end
|
2635
|
+
|
2417
2636
|
test 'should preserve passthrough placeholders when highlighting source using coderay' do
|
2418
2637
|
input = <<-EOS
|
2419
2638
|
:source-highlighter: coderay
|
@@ -2741,8 +2960,9 @@ content
|
|
2741
2960
|
part intro paragraph
|
2742
2961
|
EOS
|
2743
2962
|
|
2744
|
-
output = render_string input
|
2963
|
+
output, warnings = redirect_streams {|_, err| [(render_string input), err.string] }
|
2745
2964
|
assert_css '.partintro', output, 0
|
2965
|
+
assert_includes warnings, 'partintro block can only be used when doctype is book and it\'s a child of a book part'
|
2746
2966
|
end
|
2747
2967
|
|
2748
2968
|
test 'should not allow partintro unless doctype is book' do
|
@@ -2751,8 +2971,9 @@ part intro paragraph
|
|
2751
2971
|
part intro paragraph
|
2752
2972
|
EOS
|
2753
2973
|
|
2754
|
-
output = render_string input
|
2974
|
+
output, warnings = redirect_streams {|_, err| [(render_string input), err.string] }
|
2755
2975
|
assert_css '.partintro', output, 0
|
2976
|
+
assert_includes warnings, 'partintro block can only be used when doctype is book and it\'s a child of a book part'
|
2756
2977
|
end
|
2757
2978
|
|
2758
2979
|
test 'should accept partintro on open block without title rendered to DocBook' do
|
@@ -2814,8 +3035,9 @@ content
|
|
2814
3035
|
part intro paragraph
|
2815
3036
|
EOS
|
2816
3037
|
|
2817
|
-
output = render_string input, :backend => 'docbook'
|
3038
|
+
output, warnings = redirect_streams {|_, err| [(render_string input, :backend => 'docbook'), err.string] }
|
2818
3039
|
assert_css 'partintro', output, 0
|
3040
|
+
assert_includes warnings, 'partintro block can only be used when doctype is book and it\'s a child of a part section'
|
2819
3041
|
end
|
2820
3042
|
|
2821
3043
|
test 'should not allow partintro unless doctype is book rendered to DocBook' do
|
@@ -2824,12 +3046,26 @@ part intro paragraph
|
|
2824
3046
|
part intro paragraph
|
2825
3047
|
EOS
|
2826
3048
|
|
2827
|
-
output = render_string input, :backend => 'docbook'
|
3049
|
+
output, warnings = redirect_streams {|_, err| [(render_string input, :backend => 'docbook'), err.string] }
|
2828
3050
|
assert_css 'partintro', output, 0
|
3051
|
+
assert_includes warnings, 'partintro block can only be used when doctype is book and it\'s a child of a part section'
|
2829
3052
|
end
|
2830
3053
|
end
|
2831
3054
|
|
2832
3055
|
context 'Substitutions' do
|
3056
|
+
test 'processor should not crash if subs are empty' do
|
3057
|
+
input = <<-EOS
|
3058
|
+
[subs=","]
|
3059
|
+
....
|
3060
|
+
content
|
3061
|
+
....
|
3062
|
+
EOS
|
3063
|
+
|
3064
|
+
doc = document_from_string input
|
3065
|
+
block = doc.blocks.first
|
3066
|
+
assert_equal [], block.subs
|
3067
|
+
end
|
3068
|
+
|
2833
3069
|
test 'should be able to append subs to default block substitution list' do
|
2834
3070
|
input = <<-EOS
|
2835
3071
|
:application: Asciidoctor
|
@@ -2915,7 +3151,32 @@ content
|
|
2915
3151
|
block = doc.blocks.first
|
2916
3152
|
assert_nil block.id
|
2917
3153
|
assert_nil(block.attr 'reftext')
|
2918
|
-
assert !doc.
|
3154
|
+
assert !doc.catalog[:ids].has_key?('illegal$id')
|
3155
|
+
end
|
3156
|
+
|
3157
|
+
test 'should not recognize block anchor that starts with digit' do
|
3158
|
+
input = <<-EOS
|
3159
|
+
[[3-blind-mice]]
|
3160
|
+
--
|
3161
|
+
see how they run
|
3162
|
+
--
|
3163
|
+
EOS
|
3164
|
+
|
3165
|
+
output = render_embedded_string input
|
3166
|
+
assert_includes output, '[[3-blind-mice]]'
|
3167
|
+
assert_xpath '/*[@id = ":3-blind-mice"]', output, 0
|
3168
|
+
end
|
3169
|
+
|
3170
|
+
test 'should recognize block anchor that starts with colon' do
|
3171
|
+
input = <<-EOS
|
3172
|
+
[[:idname]]
|
3173
|
+
--
|
3174
|
+
content
|
3175
|
+
--
|
3176
|
+
EOS
|
3177
|
+
|
3178
|
+
output = render_embedded_string input
|
3179
|
+
assert_xpath '/*[@id = ":idname"]', output, 1
|
2919
3180
|
end
|
2920
3181
|
|
2921
3182
|
test 'should use specified id and reftext when registering block reference' do
|
@@ -2928,7 +3189,7 @@ $ apt-get install asciidoctor
|
|
2928
3189
|
EOS
|
2929
3190
|
|
2930
3191
|
doc = document_from_string input
|
2931
|
-
reftext = doc.
|
3192
|
+
reftext = doc.catalog[:ids]['debian']
|
2932
3193
|
refute_nil reftext
|
2933
3194
|
assert_equal 'Debian Install', reftext
|
2934
3195
|
end
|
@@ -2943,7 +3204,7 @@ $ apt-get install asciidoctor
|
|
2943
3204
|
EOS
|
2944
3205
|
|
2945
3206
|
doc = document_from_string input
|
2946
|
-
reftext = doc.
|
3207
|
+
reftext = doc.catalog[:ids]['debian']
|
2947
3208
|
refute_nil reftext
|
2948
3209
|
assert_equal '[Debian] Install', reftext
|
2949
3210
|
end
|
@@ -2958,11 +3219,30 @@ $ apt-get install asciidoctor
|
|
2958
3219
|
EOS
|
2959
3220
|
|
2960
3221
|
doc = document_from_string input
|
2961
|
-
reftext = doc.
|
3222
|
+
reftext = doc.catalog[:ids]['debian']
|
2962
3223
|
refute_nil reftext
|
2963
3224
|
assert_equal 'Debian, Ubuntu', reftext
|
2964
3225
|
end
|
2965
3226
|
|
3227
|
+
test 'should substitute attribute references in reftext when registering block reference' do
|
3228
|
+
input = <<-EOS
|
3229
|
+
:label-tiger: Tiger
|
3230
|
+
|
3231
|
+
[[tiger-evolution,Evolution of the {label-tiger}]]
|
3232
|
+
****
|
3233
|
+
Information about the evolution of the tiger.
|
3234
|
+
****
|
3235
|
+
EOS
|
3236
|
+
|
3237
|
+
doc = document_from_string input
|
3238
|
+
reftext = doc.catalog[:ids]['tiger-evolution']
|
3239
|
+
refute_nil reftext
|
3240
|
+
assert_equal 'Evolution of the Tiger', reftext
|
3241
|
+
ref = doc.catalog[:refs]['tiger-evolution']
|
3242
|
+
refute_nil ref
|
3243
|
+
assert_equal 'Evolution of the Tiger', ref.attributes['reftext']
|
3244
|
+
end
|
3245
|
+
|
2966
3246
|
test 'should use specified reftext when registering block reference' do
|
2967
3247
|
input = <<-EOS
|
2968
3248
|
[[debian]]
|
@@ -2974,7 +3254,7 @@ $ apt-get install asciidoctor
|
|
2974
3254
|
EOS
|
2975
3255
|
|
2976
3256
|
doc = document_from_string input
|
2977
|
-
reftext = doc.
|
3257
|
+
reftext = doc.catalog[:ids]['debian']
|
2978
3258
|
refute_nil reftext
|
2979
3259
|
assert_equal 'Debian Install', reftext
|
2980
3260
|
end
|