asciidoctor 1.5.8 → 2.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +11 -0
- data/CHANGELOG.adoc +628 -45
- data/LICENSE +2 -1
- data/README-de.adoc +28 -38
- data/README-fr.adoc +30 -43
- data/README-jp.adoc +255 -201
- data/README-zh_CN.adoc +40 -44
- data/README.adoc +170 -143
- data/asciidoctor.gemspec +22 -34
- data/bin/asciidoctor +5 -4
- data/data/locale/attributes-ar.adoc +4 -3
- data/data/locale/attributes-be.adoc +23 -0
- data/data/locale/attributes-bg.adoc +4 -3
- data/data/locale/attributes-ca.adoc +6 -5
- data/data/locale/attributes-cs.adoc +4 -3
- data/data/locale/attributes-da.adoc +6 -5
- data/data/locale/attributes-de.adoc +6 -5
- data/data/locale/attributes-en.adoc +4 -4
- data/data/locale/attributes-es.adoc +6 -5
- data/data/locale/attributes-fa.adoc +4 -3
- data/data/locale/attributes-fi.adoc +4 -3
- data/data/locale/attributes-fr.adoc +8 -7
- data/data/locale/attributes-hu.adoc +4 -3
- data/data/locale/attributes-id.adoc +4 -3
- data/data/locale/attributes-it.adoc +6 -5
- data/data/locale/attributes-ja.adoc +4 -3
- data/data/locale/{attributes-kr.adoc → attributes-ko.adoc} +4 -3
- data/data/locale/attributes-nb.adoc +4 -3
- data/data/locale/attributes-nl.adoc +6 -5
- data/data/locale/attributes-nn.adoc +4 -3
- data/data/locale/attributes-pl.adoc +8 -7
- data/data/locale/attributes-pt.adoc +6 -5
- data/data/locale/attributes-pt_BR.adoc +6 -5
- data/data/locale/attributes-ro.adoc +4 -3
- data/data/locale/attributes-ru.adoc +6 -5
- data/data/locale/attributes-sr.adoc +4 -4
- data/data/locale/attributes-sr_Latn.adoc +4 -4
- data/data/locale/attributes-sv.adoc +4 -4
- data/data/locale/attributes-th.adoc +23 -0
- data/data/locale/attributes-tr.adoc +4 -3
- data/data/locale/attributes-uk.adoc +6 -5
- data/data/locale/attributes-vi.adoc +23 -0
- data/data/locale/attributes-zh_CN.adoc +4 -3
- data/data/locale/attributes-zh_TW.adoc +4 -3
- data/data/reference/syntax.adoc +296 -0
- data/data/stylesheets/asciidoctor-default.css +120 -114
- data/data/stylesheets/coderay-asciidoctor.css +15 -17
- data/lib/asciidoctor/abstract_block.rb +146 -140
- data/lib/asciidoctor/abstract_node.rb +152 -170
- data/lib/asciidoctor/attribute_list.rb +77 -89
- data/lib/asciidoctor/block.rb +29 -28
- data/lib/asciidoctor/callouts.rb +4 -2
- data/lib/asciidoctor/cli/invoker.rb +20 -24
- data/lib/asciidoctor/cli/options.rb +107 -96
- data/lib/asciidoctor/cli.rb +3 -2
- data/lib/asciidoctor/convert.rb +199 -0
- data/lib/asciidoctor/converter/composite.rb +40 -48
- data/lib/asciidoctor/converter/docbook5.rb +627 -644
- data/lib/asciidoctor/converter/html5.rb +1053 -951
- data/lib/asciidoctor/converter/manpage.rb +581 -532
- data/lib/asciidoctor/converter/template.rb +232 -271
- data/lib/asciidoctor/converter.rb +370 -185
- data/lib/asciidoctor/core_ext/float/truncate.rb +20 -0
- data/lib/asciidoctor/core_ext/hash/merge.rb +8 -0
- data/lib/asciidoctor/core_ext/match_data/names.rb +7 -0
- data/lib/asciidoctor/core_ext/nil_or_empty.rb +1 -0
- data/lib/asciidoctor/core_ext/regexp/is_match.rb +4 -2
- data/lib/asciidoctor/core_ext.rb +8 -17
- data/lib/asciidoctor/document.rb +503 -461
- data/lib/asciidoctor/extensions.rb +127 -174
- data/lib/asciidoctor/helpers.rb +184 -107
- data/lib/asciidoctor/inline.rb +9 -12
- data/lib/asciidoctor/list.rb +11 -29
- data/lib/asciidoctor/load.rb +119 -0
- data/lib/asciidoctor/logging.rb +22 -17
- data/lib/asciidoctor/parser.rb +673 -719
- data/lib/asciidoctor/path_resolver.rb +48 -33
- data/lib/asciidoctor/reader.rb +383 -338
- data/lib/asciidoctor/rouge_ext.rb +39 -0
- data/lib/asciidoctor/rx.rb +723 -0
- data/lib/asciidoctor/section.rb +17 -16
- data/lib/asciidoctor/stylesheets.rb +19 -37
- data/lib/asciidoctor/substitutors.rb +926 -1022
- data/lib/asciidoctor/syntax_highlighter/coderay.rb +88 -0
- data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +34 -0
- data/lib/asciidoctor/syntax_highlighter/html_pipeline.rb +10 -0
- data/lib/asciidoctor/syntax_highlighter/prettify.rb +30 -0
- data/lib/asciidoctor/syntax_highlighter/pygments.rb +157 -0
- data/lib/asciidoctor/syntax_highlighter/rouge.rb +143 -0
- data/lib/asciidoctor/syntax_highlighter.rb +253 -0
- data/lib/asciidoctor/table.rb +152 -114
- data/lib/asciidoctor/timings.rb +7 -5
- data/lib/asciidoctor/version.rb +2 -1
- data/lib/asciidoctor/writer.rb +30 -0
- data/lib/asciidoctor.rb +266 -1340
- data/man/asciidoctor.1 +49 -47
- data/man/asciidoctor.adoc +54 -45
- metadata +50 -245
- data/CONTRIBUTING.adoc +0 -185
- data/Gemfile +0 -60
- data/Rakefile +0 -129
- data/bin/asciidoctor-safe +0 -15
- data/features/open_block.feature +0 -92
- data/features/pass_block.feature +0 -66
- data/features/step_definitions.rb +0 -49
- data/features/text_formatting.feature +0 -57
- data/features/xref.feature +0 -1039
- data/lib/asciidoctor/converter/base.rb +0 -59
- data/lib/asciidoctor/converter/docbook45.rb +0 -93
- data/lib/asciidoctor/converter/factory.rb +0 -226
- data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/concurrent/hash.rb +0 -5
- data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +0 -4
- data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +0 -5
- data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/string/limit_bytesize.rb +0 -29
- data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +0 -6
- data/lib/asciidoctor/core_ext/string/limit_bytesize.rb +0 -10
- data/test/api_test.rb +0 -1240
- data/test/attribute_list_test.rb +0 -242
- data/test/attributes_test.rb +0 -1623
- data/test/blocks_test.rb +0 -3870
- data/test/converter_test.rb +0 -470
- data/test/document_test.rb +0 -1853
- data/test/extensions_test.rb +0 -1560
- data/test/fixtures/asciidoc_index.txt +0 -521
- data/test/fixtures/basic-docinfo-footer.html +0 -6
- data/test/fixtures/basic-docinfo-footer.xml +0 -8
- data/test/fixtures/basic-docinfo.html +0 -1
- data/test/fixtures/basic-docinfo.xml +0 -4
- data/test/fixtures/basic.asciidoc +0 -5
- data/test/fixtures/chapter-a.adoc +0 -3
- data/test/fixtures/child-include.adoc +0 -5
- data/test/fixtures/circle.svg +0 -9
- data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +0 -6
- data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +0 -6
- data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +0 -3
- data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +0 -5
- data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +0 -1
- data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +0 -6
- data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +0 -3
- data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +0 -5
- data/test/fixtures/custom-docinfodir/basic-docinfo.html +0 -1
- data/test/fixtures/custom-docinfodir/docinfo.html +0 -1
- data/test/fixtures/docinfo-footer.html +0 -1
- data/test/fixtures/docinfo-footer.xml +0 -9
- data/test/fixtures/docinfo.html +0 -1
- data/test/fixtures/docinfo.xml +0 -3
- data/test/fixtures/doctime-localtime.adoc +0 -2
- data/test/fixtures/dot.gif +0 -0
- data/test/fixtures/encoding.asciidoc +0 -13
- data/test/fixtures/file-with-missing-include.adoc +0 -1
- data/test/fixtures/grandchild-include.adoc +0 -3
- data/test/fixtures/hello-asciidoctor.pdf +0 -69
- data/test/fixtures/include-file.asciidoc +0 -24
- data/test/fixtures/include-file.jsx +0 -8
- data/test/fixtures/include-file.ml +0 -3
- data/test/fixtures/include-file.xml +0 -5
- data/test/fixtures/lists.adoc +0 -96
- data/test/fixtures/master.adoc +0 -5
- data/test/fixtures/mismatched-end-tag.adoc +0 -7
- data/test/fixtures/other-chapters.adoc +0 -11
- data/test/fixtures/outer-include.adoc +0 -5
- data/test/fixtures/parent-include-restricted.adoc +0 -5
- data/test/fixtures/parent-include.adoc +0 -5
- data/test/fixtures/sample.asciidoc +0 -30
- data/test/fixtures/section-a.adoc +0 -4
- data/test/fixtures/stylesheets/custom.css +0 -3
- data/test/fixtures/subdir/index.adoc +0 -3
- data/test/fixtures/subdir/inner-include.adoc +0 -3
- data/test/fixtures/subdir/middle-include.adoc +0 -5
- data/test/fixtures/subs-docinfo.html +0 -2
- data/test/fixtures/subs.adoc +0 -6
- data/test/fixtures/tagged-class-enclosed.rb +0 -25
- data/test/fixtures/tagged-class.rb +0 -23
- data/test/fixtures/tip.gif +0 -0
- data/test/fixtures/unclosed-tag.adoc +0 -3
- data/test/fixtures/unexpected-end-tag.adoc +0 -4
- data/test/invoker_test.rb +0 -745
- data/test/links_test.rb +0 -855
- data/test/lists_test.rb +0 -5151
- data/test/logger_test.rb +0 -211
- data/test/manpage_test.rb +0 -660
- data/test/options_test.rb +0 -262
- data/test/paragraphs_test.rb +0 -562
- data/test/parser_test.rb +0 -742
- data/test/paths_test.rb +0 -395
- data/test/preamble_test.rb +0 -173
- data/test/reader_test.rb +0 -2161
- data/test/sections_test.rb +0 -3575
- data/test/substitutions_test.rb +0 -2066
- data/test/tables_test.rb +0 -2036
- data/test/test_helper.rb +0 -447
- data/test/text_test.rb +0 -309
data/test/attributes_test.rb
DELETED
@@ -1,1623 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
unless defined? ASCIIDOCTOR_PROJECT_DIR
|
3
|
-
$: << File.dirname(__FILE__); $:.uniq!
|
4
|
-
require 'test_helper'
|
5
|
-
end
|
6
|
-
|
7
|
-
context 'Attributes' do
|
8
|
-
default_logger = Asciidoctor::LoggerManager.logger
|
9
|
-
|
10
|
-
setup do
|
11
|
-
Asciidoctor::LoggerManager.logger = (@logger = Asciidoctor::MemoryLogger.new)
|
12
|
-
end
|
13
|
-
|
14
|
-
teardown do
|
15
|
-
Asciidoctor::LoggerManager.logger = default_logger
|
16
|
-
end
|
17
|
-
|
18
|
-
context 'Assignment' do
|
19
|
-
test 'creates an attribute' do
|
20
|
-
doc = document_from_string(':frog: Tanglefoot')
|
21
|
-
assert_equal 'Tanglefoot', doc.attributes['frog']
|
22
|
-
end
|
23
|
-
|
24
|
-
test 'requires a space after colon following attribute name' do
|
25
|
-
doc = document_from_string 'foo:bar'
|
26
|
-
assert_nil doc.attributes['foo']
|
27
|
-
end
|
28
|
-
|
29
|
-
# NOTE AsciiDoc Python recognizes this entry
|
30
|
-
test 'does not recognize attribute entry if name contains colon' do
|
31
|
-
input = <<-EOS.chomp
|
32
|
-
:foo:bar: baz
|
33
|
-
EOS
|
34
|
-
doc = document_from_string input
|
35
|
-
refute doc.attr?('foo:bar')
|
36
|
-
assert_equal 1, doc.blocks.size
|
37
|
-
assert_equal :paragraph, doc.blocks[0].context
|
38
|
-
end
|
39
|
-
|
40
|
-
# NOTE AsciiDoc Python recognizes this entry
|
41
|
-
test 'does not recognize attribute entry if name ends with colon' do
|
42
|
-
input = <<-EOS.chomp
|
43
|
-
:foo:: bar
|
44
|
-
EOS
|
45
|
-
doc = document_from_string input
|
46
|
-
refute doc.attr?('foo:')
|
47
|
-
assert_equal 1, doc.blocks.size
|
48
|
-
assert_equal :dlist, doc.blocks[0].context
|
49
|
-
end
|
50
|
-
|
51
|
-
# NOTE AsciiDoc Python does not recognize this entry
|
52
|
-
test 'allows any word character defined by Unicode in an attribute name' do
|
53
|
-
[['café', 'a coffee shop'], ['سمن', %(سازمان مردمنهاد)]].each do |(name, value)|
|
54
|
-
str = <<-EOS
|
55
|
-
:#{name}: #{value}
|
56
|
-
|
57
|
-
{#{name}}
|
58
|
-
EOS
|
59
|
-
result = convert_string_to_embedded str
|
60
|
-
assert_includes result, %(<p>#{value}</p>)
|
61
|
-
end
|
62
|
-
|
63
|
-
end if ::RUBY_MIN_VERSION_1_9
|
64
|
-
|
65
|
-
test 'creates an attribute by fusing a legacy multi-line value' do
|
66
|
-
str = <<-EOS
|
67
|
-
:description: This is the first +
|
68
|
-
Ruby implementation of +
|
69
|
-
AsciiDoc.
|
70
|
-
EOS
|
71
|
-
doc = document_from_string(str)
|
72
|
-
assert_equal 'This is the first Ruby implementation of AsciiDoc.', doc.attributes['description']
|
73
|
-
end
|
74
|
-
|
75
|
-
test 'creates an attribute by fusing a multi-line value' do
|
76
|
-
str = <<-EOS
|
77
|
-
:description: This is the first \\
|
78
|
-
Ruby implementation of \\
|
79
|
-
AsciiDoc.
|
80
|
-
EOS
|
81
|
-
doc = document_from_string(str)
|
82
|
-
assert_equal 'This is the first Ruby implementation of AsciiDoc.', doc.attributes['description']
|
83
|
-
end
|
84
|
-
|
85
|
-
test 'honors line break characters in multi-line values' do
|
86
|
-
str = <<-EOS
|
87
|
-
:signature: Linus Torvalds + \\
|
88
|
-
Linux Hacker + \\
|
89
|
-
linus.torvalds@example.com
|
90
|
-
EOS
|
91
|
-
doc = document_from_string(str)
|
92
|
-
assert_equal %(Linus Torvalds +\nLinux Hacker +\nlinus.torvalds@example.com), doc.attributes['signature']
|
93
|
-
end
|
94
|
-
|
95
|
-
test 'should allow pass macro to surround a multi-line value that contains line breaks' do
|
96
|
-
str = <<-EOS
|
97
|
-
:signature: pass:a[{author} + \\
|
98
|
-
{title} + \\
|
99
|
-
{email}]
|
100
|
-
EOS
|
101
|
-
doc = document_from_string str, :attributes => { 'author' => 'Linus Torvalds', 'title' => 'Linux Hacker', 'email' => 'linus.torvalds@example.com' }
|
102
|
-
assert_equal %(Linus Torvalds +\nLinux Hacker +\nlinus.torvalds@example.com), (doc.attr 'signature')
|
103
|
-
end
|
104
|
-
|
105
|
-
test 'should delete an attribute that ends with !' do
|
106
|
-
doc = document_from_string(":frog: Tanglefoot\n:frog!:")
|
107
|
-
assert_nil doc.attributes['frog']
|
108
|
-
end
|
109
|
-
|
110
|
-
test 'should delete an attribute that ends with ! set via API' do
|
111
|
-
doc = document_from_string(":frog: Tanglefoot", :attributes => {'frog!' => ''})
|
112
|
-
assert_nil doc.attributes['frog']
|
113
|
-
end
|
114
|
-
|
115
|
-
test 'should delete an attribute that begins with !' do
|
116
|
-
doc = document_from_string(":frog: Tanglefoot\n:!frog:")
|
117
|
-
assert_nil doc.attributes['frog']
|
118
|
-
end
|
119
|
-
|
120
|
-
test 'should delete an attribute that begins with ! set via API' do
|
121
|
-
doc = document_from_string(":frog: Tanglefoot", :attributes => {'!frog' => ''})
|
122
|
-
assert_nil doc.attributes['frog']
|
123
|
-
end
|
124
|
-
|
125
|
-
test 'should delete an attribute set via API to nil value' do
|
126
|
-
doc = document_from_string(":frog: Tanglefoot", :attributes => {'frog' => nil})
|
127
|
-
assert_nil doc.attributes['frog']
|
128
|
-
end
|
129
|
-
|
130
|
-
test "doesn't choke when deleting a non-existing attribute" do
|
131
|
-
doc = document_from_string(':frog!:')
|
132
|
-
assert_nil doc.attributes['frog']
|
133
|
-
end
|
134
|
-
|
135
|
-
test "replaces special characters in attribute value" do
|
136
|
-
doc = document_from_string(":xml-busters: <>&")
|
137
|
-
assert_equal '<>&', doc.attributes['xml-busters']
|
138
|
-
end
|
139
|
-
|
140
|
-
test "performs attribute substitution on attribute value" do
|
141
|
-
doc = document_from_string(":version: 1.0\n:release: Asciidoctor {version}")
|
142
|
-
assert_equal 'Asciidoctor 1.0', doc.attributes['release']
|
143
|
-
end
|
144
|
-
|
145
|
-
test 'assigns attribute to empty string if substitution fails to resolve attribute' do
|
146
|
-
input = ':release: Asciidoctor {version}'
|
147
|
-
document_from_string input, :attributes => { 'attribute-missing' => 'drop-line' }
|
148
|
-
assert_message @logger, :WARN, 'dropping line containing reference to missing attribute: version'
|
149
|
-
end
|
150
|
-
|
151
|
-
test 'assigns multi-line attribute to empty string if substitution fails to resolve attribute' do
|
152
|
-
input = <<-EOS
|
153
|
-
:release: Asciidoctor +
|
154
|
-
{version}
|
155
|
-
EOS
|
156
|
-
doc = document_from_string input, :attributes => { 'attribute-missing' => 'drop-line' }
|
157
|
-
assert_equal '', doc.attributes['release']
|
158
|
-
assert_message @logger, :WARN, 'dropping line containing reference to missing attribute: version'
|
159
|
-
end
|
160
|
-
|
161
|
-
test 'resolves attributes inside attribute value within header' do
|
162
|
-
input = <<-EOS
|
163
|
-
= Document Title
|
164
|
-
:big: big
|
165
|
-
:bigfoot: {big}foot
|
166
|
-
|
167
|
-
{bigfoot}
|
168
|
-
EOS
|
169
|
-
|
170
|
-
result = convert_string_to_embedded input
|
171
|
-
assert_includes result, 'bigfoot'
|
172
|
-
end
|
173
|
-
|
174
|
-
test 'resolves attributes and pass macro inside attribute value outside header' do
|
175
|
-
input = <<-EOS
|
176
|
-
= Document Title
|
177
|
-
|
178
|
-
content
|
179
|
-
|
180
|
-
:big: pass:a,q[_big_]
|
181
|
-
:bigfoot: {big}foot
|
182
|
-
{bigfoot}
|
183
|
-
EOS
|
184
|
-
|
185
|
-
result = convert_string_to_embedded input
|
186
|
-
assert_includes result, '<em>big</em>foot'
|
187
|
-
end
|
188
|
-
|
189
|
-
test 'should limit maximum size of attribute value if safe mode is SECURE' do
|
190
|
-
expected = 'a' * 4096
|
191
|
-
input = <<-EOS
|
192
|
-
:name: #{'a' * 5000}
|
193
|
-
|
194
|
-
{name}
|
195
|
-
EOS
|
196
|
-
|
197
|
-
result = convert_inline_string input
|
198
|
-
assert_equal expected, result
|
199
|
-
assert_equal 4096, result.bytesize
|
200
|
-
end
|
201
|
-
|
202
|
-
test 'should handle multibyte characters when limiting attribute value size' do
|
203
|
-
expected = '日本'
|
204
|
-
input = <<-EOS
|
205
|
-
:name: 日本語
|
206
|
-
|
207
|
-
{name}
|
208
|
-
EOS
|
209
|
-
|
210
|
-
result = convert_inline_string input, :attributes => { 'max-attribute-value-size' => 6 }
|
211
|
-
assert_equal expected, result
|
212
|
-
assert_equal 6, result.bytesize
|
213
|
-
end
|
214
|
-
|
215
|
-
test 'should not mangle multibyte characters when limiting attribute value size' do
|
216
|
-
expected = '日本'
|
217
|
-
input = <<-EOS
|
218
|
-
:name: 日本語
|
219
|
-
|
220
|
-
{name}
|
221
|
-
EOS
|
222
|
-
|
223
|
-
result = convert_inline_string input, :attributes => { 'max-attribute-value-size' => 8 }
|
224
|
-
assert_equal expected, result
|
225
|
-
assert_equal 6, result.bytesize
|
226
|
-
end
|
227
|
-
|
228
|
-
test 'should allow maximize size of attribute value to be disabled' do
|
229
|
-
expected = 'a' * 5000
|
230
|
-
input = <<-EOS
|
231
|
-
:name: #{'a' * 5000}
|
232
|
-
|
233
|
-
{name}
|
234
|
-
EOS
|
235
|
-
|
236
|
-
result = convert_inline_string input, :attributes => { 'max-attribute-value-size' => nil }
|
237
|
-
assert_equal expected, result
|
238
|
-
assert_equal 5000, result.bytesize
|
239
|
-
end
|
240
|
-
|
241
|
-
test 'resolves user-home attribute if safe mode is less than SERVER' do
|
242
|
-
input = <<-EOS
|
243
|
-
:imagesdir: {user-home}/etc/images
|
244
|
-
|
245
|
-
{imagesdir}
|
246
|
-
EOS
|
247
|
-
output = convert_inline_string input, :safe => :safe
|
248
|
-
if RUBY_VERSION >= '1.9'
|
249
|
-
assert_equal %(#{Dir.home}/etc/images), output
|
250
|
-
else
|
251
|
-
assert_equal %(#{ENV['HOME']}/etc/images), output
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
test 'user-home attribute resolves to . if safe mode is SERVER or greater' do
|
256
|
-
input = <<-EOS
|
257
|
-
:imagesdir: {user-home}/etc/images
|
258
|
-
|
259
|
-
{imagesdir}
|
260
|
-
EOS
|
261
|
-
output = convert_inline_string input, :safe => :server
|
262
|
-
assert_equal './etc/images', output
|
263
|
-
end
|
264
|
-
|
265
|
-
test "apply custom substitutions to text in passthrough macro and assign to attribute" do
|
266
|
-
doc = document_from_string(":xml-busters: pass:[<>&]")
|
267
|
-
assert_equal '<>&', doc.attributes['xml-busters']
|
268
|
-
doc = document_from_string(":xml-busters: pass:none[<>&]")
|
269
|
-
assert_equal '<>&', doc.attributes['xml-busters']
|
270
|
-
doc = document_from_string(":xml-busters: pass:specialcharacters[<>&]")
|
271
|
-
assert_equal '<>&', doc.attributes['xml-busters']
|
272
|
-
end
|
273
|
-
|
274
|
-
test 'should not recognize pass macro with invalid substitution list in attribute value' do
|
275
|
-
[',', '42', 'a,'].each do |subs|
|
276
|
-
doc = document_from_string %(:pass-fail: pass:#{subs}[whale])
|
277
|
-
assert_equal %(pass:#{subs}[whale]), doc.attributes['pass-fail']
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
test "attribute is treated as defined until it's not" do
|
282
|
-
input = <<-EOS
|
283
|
-
:holygrail:
|
284
|
-
ifdef::holygrail[]
|
285
|
-
The holy grail has been found!
|
286
|
-
endif::holygrail[]
|
287
|
-
|
288
|
-
:holygrail!:
|
289
|
-
ifndef::holygrail[]
|
290
|
-
Buggers! What happened to the grail?
|
291
|
-
endif::holygrail[]
|
292
|
-
EOS
|
293
|
-
output = convert_string input
|
294
|
-
assert_xpath '//p', output, 2
|
295
|
-
assert_xpath '(//p)[1][text() = "The holy grail has been found!"]', output, 1
|
296
|
-
assert_xpath '(//p)[2][text() = "Buggers! What happened to the grail?"]', output, 1
|
297
|
-
end
|
298
|
-
|
299
|
-
test 'attribute set via API overrides attribute set in document' do
|
300
|
-
doc = document_from_string(':cash: money', :attributes => {'cash' => 'heroes'})
|
301
|
-
assert_equal 'heroes', doc.attributes['cash']
|
302
|
-
end
|
303
|
-
|
304
|
-
test 'attribute set via API cannot be unset by document' do
|
305
|
-
doc = document_from_string(':cash!:', :attributes => {'cash' => 'heroes'})
|
306
|
-
assert_equal 'heroes', doc.attributes['cash']
|
307
|
-
end
|
308
|
-
|
309
|
-
test 'attribute soft set via API using modifier on name can be overridden by document' do
|
310
|
-
doc = document_from_string(':cash: money', :attributes => {'cash@' => 'heroes'})
|
311
|
-
assert_equal 'money', doc.attributes['cash']
|
312
|
-
end
|
313
|
-
|
314
|
-
test 'attribute soft set via API using modifier on value can be overridden by document' do
|
315
|
-
doc = document_from_string(':cash: money', :attributes => {'cash' => 'heroes@'})
|
316
|
-
assert_equal 'money', doc.attributes['cash']
|
317
|
-
end
|
318
|
-
|
319
|
-
test 'attribute soft set via API using modifier on name can be unset by document' do
|
320
|
-
doc = document_from_string(':cash!:', :attributes => {'cash@' => 'heroes'})
|
321
|
-
assert_nil doc.attributes['cash']
|
322
|
-
doc = document_from_string(':cash!:', :attributes => {'cash@' => true})
|
323
|
-
assert_nil doc.attributes['cash']
|
324
|
-
end
|
325
|
-
|
326
|
-
test 'attribute soft set via API using modifier on value can be unset by document' do
|
327
|
-
doc = document_from_string(':cash!:', :attributes => {'cash' => 'heroes@'})
|
328
|
-
assert_nil doc.attributes['cash']
|
329
|
-
end
|
330
|
-
|
331
|
-
test 'attribute unset via API cannot be set by document' do
|
332
|
-
[
|
333
|
-
{ 'cash!' => '' },
|
334
|
-
{ '!cash' => '' },
|
335
|
-
{ 'cash' => nil },
|
336
|
-
].each do |attributes|
|
337
|
-
doc = document_from_string(':cash: money', :attributes => attributes)
|
338
|
-
assert_nil doc.attributes['cash']
|
339
|
-
end
|
340
|
-
end
|
341
|
-
|
342
|
-
test 'attribute soft unset via API can be set by document' do
|
343
|
-
[
|
344
|
-
{ 'cash!@' => '' },
|
345
|
-
{ '!cash@' => '' },
|
346
|
-
{ 'cash!' => '@' },
|
347
|
-
{ '!cash' => '@' },
|
348
|
-
{ 'cash' => false },
|
349
|
-
].each do |attributes|
|
350
|
-
doc = document_from_string(':cash: money', :attributes => attributes)
|
351
|
-
assert_equal 'money', doc.attributes['cash']
|
352
|
-
end
|
353
|
-
end
|
354
|
-
|
355
|
-
test 'can soft unset built-in attribute from API and still override in document' do
|
356
|
-
[
|
357
|
-
{ 'sectids!@' => '' },
|
358
|
-
{ '!sectids@' => '' },
|
359
|
-
{ 'sectids!' => '@' },
|
360
|
-
{ '!sectids' => '@' },
|
361
|
-
{ 'sectids' => false },
|
362
|
-
].each do |attributes|
|
363
|
-
doc = document_from_string '== Heading', :attributes => attributes
|
364
|
-
refute doc.attr?('sectids')
|
365
|
-
assert_css '#_heading', (doc.convert :header_footer => false), 0
|
366
|
-
doc = document_from_string %(:sectids:\n\n== Heading), :attributes => attributes
|
367
|
-
assert doc.attr?('sectids')
|
368
|
-
assert_css '#_heading', (doc.convert :header_footer => false), 1
|
369
|
-
end
|
370
|
-
end
|
371
|
-
|
372
|
-
test 'backend and doctype attributes are set by default in default configuration' do
|
373
|
-
input = <<-EOS
|
374
|
-
= Document Title
|
375
|
-
Author Name
|
376
|
-
|
377
|
-
content
|
378
|
-
EOS
|
379
|
-
|
380
|
-
doc = document_from_string input
|
381
|
-
expect = {
|
382
|
-
'backend' => 'html5',
|
383
|
-
'backend-html5' => '',
|
384
|
-
'backend-html5-doctype-article' => '',
|
385
|
-
'outfilesuffix' => '.html',
|
386
|
-
'basebackend' => 'html',
|
387
|
-
'basebackend-html' => '',
|
388
|
-
'basebackend-html-doctype-article' => '',
|
389
|
-
'doctype' => 'article',
|
390
|
-
'doctype-article' => '',
|
391
|
-
'filetype' => 'html',
|
392
|
-
'filetype-html' => ''
|
393
|
-
}
|
394
|
-
expect.each do |key, val|
|
395
|
-
assert doc.attributes.key? key
|
396
|
-
assert_equal val, doc.attributes[key]
|
397
|
-
end
|
398
|
-
end
|
399
|
-
|
400
|
-
test 'backend and doctype attributes are set by default in custom configuration' do
|
401
|
-
input = <<-EOS
|
402
|
-
= Document Title
|
403
|
-
Author Name
|
404
|
-
|
405
|
-
content
|
406
|
-
EOS
|
407
|
-
|
408
|
-
doc = document_from_string input, :doctype => 'book', :backend => 'docbook'
|
409
|
-
expect = {
|
410
|
-
'backend' => 'docbook5',
|
411
|
-
'backend-docbook5' => '',
|
412
|
-
'backend-docbook5-doctype-book' => '',
|
413
|
-
'outfilesuffix' => '.xml',
|
414
|
-
'basebackend' => 'docbook',
|
415
|
-
'basebackend-docbook' => '',
|
416
|
-
'basebackend-docbook-doctype-book' => '',
|
417
|
-
'doctype' => 'book',
|
418
|
-
'doctype-book' => '',
|
419
|
-
'filetype' => 'xml',
|
420
|
-
'filetype-xml' => ''
|
421
|
-
}
|
422
|
-
expect.each do |key, val|
|
423
|
-
assert doc.attributes.key? key
|
424
|
-
assert_equal val, doc.attributes[key]
|
425
|
-
end
|
426
|
-
end
|
427
|
-
|
428
|
-
test 'backend attributes are updated if backend attribute is defined in document and safe mode is less than SERVER' do
|
429
|
-
input = <<-EOS
|
430
|
-
= Document Title
|
431
|
-
Author Name
|
432
|
-
:backend: docbook
|
433
|
-
:doctype: book
|
434
|
-
|
435
|
-
content
|
436
|
-
EOS
|
437
|
-
|
438
|
-
doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE
|
439
|
-
expect = {
|
440
|
-
'backend' => 'docbook5',
|
441
|
-
'backend-docbook5' => '',
|
442
|
-
'backend-docbook5-doctype-book' => '',
|
443
|
-
'outfilesuffix' => '.xml',
|
444
|
-
'basebackend' => 'docbook',
|
445
|
-
'basebackend-docbook' => '',
|
446
|
-
'basebackend-docbook-doctype-book' => '',
|
447
|
-
'doctype' => 'book',
|
448
|
-
'doctype-book' => '',
|
449
|
-
'filetype' => 'xml',
|
450
|
-
'filetype-xml' => ''
|
451
|
-
}
|
452
|
-
expect.each do |key, val|
|
453
|
-
assert doc.attributes.key?(key)
|
454
|
-
assert_equal val, doc.attributes[key]
|
455
|
-
end
|
456
|
-
|
457
|
-
refute doc.attributes.key?('backend-html5')
|
458
|
-
refute doc.attributes.key?('backend-html5-doctype-article')
|
459
|
-
refute doc.attributes.key?('basebackend-html')
|
460
|
-
refute doc.attributes.key?('basebackend-html-doctype-article')
|
461
|
-
refute doc.attributes.key?('doctype-article')
|
462
|
-
refute doc.attributes.key?('filetype-html')
|
463
|
-
end
|
464
|
-
|
465
|
-
test 'backend attributes defined in document options overrides backend attribute in document' do
|
466
|
-
doc = document_from_string(':backend: docbook45', :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'backend' => 'html5'})
|
467
|
-
assert_equal 'html5', doc.attributes['backend']
|
468
|
-
assert doc.attributes.has_key? 'backend-html5'
|
469
|
-
assert_equal 'html', doc.attributes['basebackend']
|
470
|
-
assert doc.attributes.has_key? 'basebackend-html'
|
471
|
-
end
|
472
|
-
|
473
|
-
test 'can only access a positional attribute from the attributes hash' do
|
474
|
-
node = Asciidoctor::Block.new nil, :paragraph, :attributes => { 1 => 'position 1' }
|
475
|
-
assert_nil node.attr(1)
|
476
|
-
refute node.attr?(1)
|
477
|
-
assert_equal 'position 1', node.attributes[1]
|
478
|
-
end
|
479
|
-
|
480
|
-
test 'set_attr should set value to empty string if no value is specified' do
|
481
|
-
node = Asciidoctor::Block.new nil, :paragraph, :attributes => {}
|
482
|
-
node.set_attr 'foo'
|
483
|
-
assert_equal '', (node.attr 'foo')
|
484
|
-
end
|
485
|
-
|
486
|
-
test 'remove_attr should remove attribute and return previous value' do
|
487
|
-
doc = empty_document
|
488
|
-
node = Asciidoctor::Block.new doc, :paragraph, :attributes => { 'foo' => 'bar' }
|
489
|
-
assert_equal 'bar', (node.remove_attr 'foo')
|
490
|
-
assert_nil node.attr('foo')
|
491
|
-
end
|
492
|
-
|
493
|
-
test 'set_attr should not overwrite existing key if overwrite is false' do
|
494
|
-
node = Asciidoctor::Block.new nil, :paragraph, :attributes => { 'foo' => 'bar' }
|
495
|
-
assert_equal 'bar', (node.attr 'foo')
|
496
|
-
node.set_attr 'foo', 'baz', false
|
497
|
-
assert_equal 'bar', (node.attr 'foo')
|
498
|
-
end
|
499
|
-
|
500
|
-
test 'set_attr should overwrite existing key by default' do
|
501
|
-
node = Asciidoctor::Block.new nil, :paragraph, :attributes => { 'foo' => 'bar' }
|
502
|
-
assert_equal 'bar', (node.attr 'foo')
|
503
|
-
node.set_attr 'foo', 'baz'
|
504
|
-
assert_equal 'baz', (node.attr 'foo')
|
505
|
-
end
|
506
|
-
|
507
|
-
test 'set_attr should set header attribute in loaded document' do
|
508
|
-
input = <<-EOS
|
509
|
-
:uri: http://example.org
|
510
|
-
|
511
|
-
{uri}
|
512
|
-
EOS
|
513
|
-
|
514
|
-
doc = Asciidoctor.load input, :attributes => { 'uri' => 'https://github.com' }
|
515
|
-
doc.set_attr 'uri', 'https://google.com'
|
516
|
-
output = doc.convert
|
517
|
-
assert_xpath '//a[@href="https://google.com"]', output, 1
|
518
|
-
end
|
519
|
-
|
520
|
-
test 'set_attribute should set attribute if key is not locked' do
|
521
|
-
doc = empty_document
|
522
|
-
refute doc.attr? 'foo'
|
523
|
-
res = doc.set_attribute 'foo', 'baz'
|
524
|
-
assert res
|
525
|
-
assert_equal 'baz', (doc.attr 'foo')
|
526
|
-
end
|
527
|
-
|
528
|
-
test 'set_attribute should not set key if key is locked' do
|
529
|
-
doc = empty_document :attributes => { 'foo' => 'bar' }
|
530
|
-
assert_equal 'bar', (doc.attr 'foo')
|
531
|
-
res = doc.set_attribute 'foo', 'baz'
|
532
|
-
refute res
|
533
|
-
assert_equal 'bar', (doc.attr 'foo')
|
534
|
-
end
|
535
|
-
|
536
|
-
test 'set_attribute should update backend attributes' do
|
537
|
-
doc = empty_document :attributes => { 'backend' => 'html5@' }
|
538
|
-
assert_equal '', (doc.attr 'backend-html5')
|
539
|
-
res = doc.set_attribute 'backend', 'docbook5'
|
540
|
-
assert res
|
541
|
-
refute doc.attr? 'backend-html5'
|
542
|
-
assert_equal '', (doc.attr 'backend-docbook5')
|
543
|
-
end
|
544
|
-
|
545
|
-
test 'verify toc attribute matrix' do
|
546
|
-
expected_data = <<-EOS
|
547
|
-
#attributes |toc|toc-position|toc-placement|toc-class
|
548
|
-
toc | |nil |auto |nil
|
549
|
-
toc=header | |nil |auto |nil
|
550
|
-
toc=beeboo | |nil |auto |nil
|
551
|
-
toc=left | |left |auto |toc2
|
552
|
-
toc2 | |left |auto |toc2
|
553
|
-
toc=right | |right |auto |toc2
|
554
|
-
toc=preamble | |content |preamble |nil
|
555
|
-
toc=macro | |content |macro |nil
|
556
|
-
toc toc-placement=macro toc-position=left | |content |macro |nil
|
557
|
-
toc toc-placement! | |content |macro |nil
|
558
|
-
EOS
|
559
|
-
|
560
|
-
expected = expected_data.strip.lines.map {|l|
|
561
|
-
next if l.start_with? '#'
|
562
|
-
l.split('|').map {|e| (e = e.strip) == 'nil' ? nil : e }
|
563
|
-
}.compact
|
564
|
-
|
565
|
-
expected.each do |expect|
|
566
|
-
raw_attrs, toc, toc_position, toc_placement, toc_class = expect
|
567
|
-
attrs = Hash[*raw_attrs.split.map {|e| e.include?('=') ? e.split('=', 2) : [e, ''] }.flatten]
|
568
|
-
doc = document_from_string '', :attributes => attrs
|
569
|
-
toc ? (assert doc.attr?('toc', toc)) : (refute doc.attr?('toc'))
|
570
|
-
toc_position ? (assert doc.attr?('toc-position', toc_position)) : (refute doc.attr?('toc-position'))
|
571
|
-
toc_placement ? (assert doc.attr?('toc-placement', toc_placement)) : (refute doc.attr?('toc-placement'))
|
572
|
-
toc_class ? (assert doc.attr?('toc-class', toc_class)) : (refute doc.attr?('toc-class'))
|
573
|
-
end
|
574
|
-
end
|
575
|
-
end
|
576
|
-
|
577
|
-
context 'Interpolation' do
|
578
|
-
|
579
|
-
test "convert properly with simple names" do
|
580
|
-
html = convert_string(":frog: Tanglefoot\n:my_super-hero: Spiderman\n\nYo, {frog}!\nBeat {my_super-hero}!")
|
581
|
-
result = Nokogiri::HTML(html)
|
582
|
-
assert_equal "Yo, Tanglefoot!\nBeat Spiderman!", result.css("p").first.content.strip
|
583
|
-
end
|
584
|
-
|
585
|
-
test 'attribute lookup is not case sensitive' do
|
586
|
-
input = <<-EOS
|
587
|
-
:He-Man: The most powerful man in the universe
|
588
|
-
|
589
|
-
He-Man: {He-Man}
|
590
|
-
|
591
|
-
She-Ra: {She-Ra}
|
592
|
-
EOS
|
593
|
-
result = convert_string_to_embedded input, :attributes => {'She-Ra' => 'The Princess of Power'}
|
594
|
-
assert_xpath '//p[text()="He-Man: The most powerful man in the universe"]', result, 1
|
595
|
-
assert_xpath '//p[text()="She-Ra: The Princess of Power"]', result, 1
|
596
|
-
end
|
597
|
-
|
598
|
-
test "convert properly with single character name" do
|
599
|
-
html = convert_string(":r: Ruby\n\nR is for {r}!")
|
600
|
-
result = Nokogiri::HTML(html)
|
601
|
-
assert_equal 'R is for Ruby!', result.css("p").first.content.strip
|
602
|
-
end
|
603
|
-
|
604
|
-
test "collapses spaces in attribute names" do
|
605
|
-
input = <<-EOS
|
606
|
-
Main Header
|
607
|
-
===========
|
608
|
-
:My frog: Tanglefoot
|
609
|
-
|
610
|
-
Yo, {myfrog}!
|
611
|
-
EOS
|
612
|
-
output = convert_string input
|
613
|
-
assert_xpath '(//p)[1][text()="Yo, Tanglefoot!"]', output, 1
|
614
|
-
end
|
615
|
-
|
616
|
-
test 'ignores lines with bad attributes if attribute-missing is drop-line' do
|
617
|
-
input = <<-EOS
|
618
|
-
:attribute-missing: drop-line
|
619
|
-
|
620
|
-
This is
|
621
|
-
blah blah {foobarbaz}
|
622
|
-
all there is.
|
623
|
-
EOS
|
624
|
-
output = convert_string_to_embedded input
|
625
|
-
para = xmlnodes_at_css 'p', output, 1
|
626
|
-
refute_includes 'blah blah', para.content
|
627
|
-
assert_message @logger, :WARN, 'dropping line containing reference to missing attribute: foobarbaz'
|
628
|
-
end
|
629
|
-
|
630
|
-
test "attribute value gets interpretted when converting" do
|
631
|
-
doc = document_from_string(":google: http://google.com[Google]\n\n{google}")
|
632
|
-
assert_equal 'http://google.com[Google]', doc.attributes['google']
|
633
|
-
output = doc.convert
|
634
|
-
assert_xpath '//a[@href="http://google.com"][text() = "Google"]', output, 1
|
635
|
-
end
|
636
|
-
|
637
|
-
test 'should drop line with reference to missing attribute if attribute-missing attribute is drop-line' do
|
638
|
-
input = <<-EOS
|
639
|
-
:attribute-missing: drop-line
|
640
|
-
|
641
|
-
Line 1: This line should appear in the output.
|
642
|
-
Line 2: Oh no, a {bogus-attribute}! This line should not appear in the output.
|
643
|
-
EOS
|
644
|
-
|
645
|
-
output = convert_string_to_embedded input
|
646
|
-
assert_match(/Line 1/, output)
|
647
|
-
refute_match(/Line 2/, output)
|
648
|
-
assert_message @logger, :WARN, 'dropping line containing reference to missing attribute: bogus-attribute'
|
649
|
-
end
|
650
|
-
|
651
|
-
test 'should not drop line with reference to missing attribute by default' do
|
652
|
-
input = <<-EOS
|
653
|
-
Line 1: This line should appear in the output.
|
654
|
-
Line 2: A {bogus-attribute}! This time, this line should appear in the output.
|
655
|
-
EOS
|
656
|
-
|
657
|
-
output = convert_string_to_embedded input
|
658
|
-
assert_match(/Line 1/, output)
|
659
|
-
assert_match(/Line 2/, output)
|
660
|
-
assert_match(/\{bogus-attribute\}/, output)
|
661
|
-
end
|
662
|
-
|
663
|
-
test 'should drop line with attribute unassignment by default' do
|
664
|
-
input = <<-EOS
|
665
|
-
:a:
|
666
|
-
|
667
|
-
Line 1: This line should appear in the output.
|
668
|
-
Line 2: {set:a!}This line should not appear in the output.
|
669
|
-
EOS
|
670
|
-
|
671
|
-
output = convert_string_to_embedded input
|
672
|
-
assert_match(/Line 1/, output)
|
673
|
-
refute_match(/Line 2/, output)
|
674
|
-
end
|
675
|
-
|
676
|
-
test 'should not drop line with attribute unassignment if attribute-undefined is drop' do
|
677
|
-
input = <<-EOS
|
678
|
-
:attribute-undefined: drop
|
679
|
-
:a:
|
680
|
-
|
681
|
-
Line 1: This line should appear in the output.
|
682
|
-
Line 2: {set:a!}This line should appear in the output.
|
683
|
-
EOS
|
684
|
-
|
685
|
-
output = convert_string_to_embedded input
|
686
|
-
assert_match(/Line 1/, output)
|
687
|
-
assert_match(/Line 2/, output)
|
688
|
-
refute_match(/\{set:a!\}/, output)
|
689
|
-
end
|
690
|
-
|
691
|
-
test 'should drop line that only contains attribute assignment' do
|
692
|
-
input = <<-EOS
|
693
|
-
Line 1
|
694
|
-
{set:a}
|
695
|
-
Line 2
|
696
|
-
EOS
|
697
|
-
|
698
|
-
output = convert_string_to_embedded input
|
699
|
-
assert_xpath %(//p[text()="Line 1\nLine 2"]), output, 1
|
700
|
-
end
|
701
|
-
|
702
|
-
test 'should drop line that only contains unresolved attribute when attribute-missing is drop' do
|
703
|
-
input = <<-EOS
|
704
|
-
Line 1
|
705
|
-
{unresolved}
|
706
|
-
Line 2
|
707
|
-
EOS
|
708
|
-
|
709
|
-
output = convert_string_to_embedded input, :attributes => { 'attribute-missing' => 'drop' }
|
710
|
-
assert_xpath %(//p[text()="Line 1\nLine 2"]), output, 1
|
711
|
-
end
|
712
|
-
|
713
|
-
test "substitutes inside unordered list items" do
|
714
|
-
html = convert_string(":foo: bar\n* snort at the {foo}\n* yawn")
|
715
|
-
result = Nokogiri::HTML(html)
|
716
|
-
assert_match(/snort at the bar/, result.css("li").first.content.strip)
|
717
|
-
end
|
718
|
-
|
719
|
-
test 'substitutes inside section title' do
|
720
|
-
output = convert_string(":prefix: Cool\n\n== {prefix} Title\n\ncontent")
|
721
|
-
result = Nokogiri::HTML(output)
|
722
|
-
assert_match(/Cool Title/, result.css('h2').first.content)
|
723
|
-
assert_match(/_cool_title/, result.css('h2').first.attr('id'))
|
724
|
-
end
|
725
|
-
|
726
|
-
test 'interpolates attribute defined in header inside attribute entry in header' do
|
727
|
-
input = <<-EOS
|
728
|
-
= Title
|
729
|
-
Author Name
|
730
|
-
:attribute-a: value
|
731
|
-
:attribute-b: {attribute-a}
|
732
|
-
|
733
|
-
preamble
|
734
|
-
EOS
|
735
|
-
doc = document_from_string(input, :parse_header_only => true)
|
736
|
-
assert_equal 'value', doc.attributes['attribute-b']
|
737
|
-
end
|
738
|
-
|
739
|
-
test 'interpolates author attribute inside attribute entry in header' do
|
740
|
-
input = <<-EOS
|
741
|
-
= Title
|
742
|
-
Author Name
|
743
|
-
:name: {author}
|
744
|
-
|
745
|
-
preamble
|
746
|
-
EOS
|
747
|
-
doc = document_from_string(input, :parse_header_only => true)
|
748
|
-
assert_equal 'Author Name', doc.attributes['name']
|
749
|
-
end
|
750
|
-
|
751
|
-
test 'interpolates revinfo attribute inside attribute entry in header' do
|
752
|
-
input = <<-EOS
|
753
|
-
= Title
|
754
|
-
Author Name
|
755
|
-
2013-01-01
|
756
|
-
:date: {revdate}
|
757
|
-
|
758
|
-
preamble
|
759
|
-
EOS
|
760
|
-
doc = document_from_string(input, :parse_header_only => true)
|
761
|
-
assert_equal '2013-01-01', doc.attributes['date']
|
762
|
-
end
|
763
|
-
|
764
|
-
test 'attribute entries can resolve previously defined attributes' do
|
765
|
-
input = <<-EOS
|
766
|
-
= Title
|
767
|
-
Author Name
|
768
|
-
v1.0, 2010-01-01: First release!
|
769
|
-
:a: value
|
770
|
-
:a2: {a}
|
771
|
-
:revdate2: {revdate}
|
772
|
-
|
773
|
-
{a} == {a2}
|
774
|
-
|
775
|
-
{revdate} == {revdate2}
|
776
|
-
EOS
|
777
|
-
|
778
|
-
doc = document_from_string input
|
779
|
-
assert_equal '2010-01-01', doc.attr('revdate')
|
780
|
-
assert_equal '2010-01-01', doc.attr('revdate2')
|
781
|
-
assert_equal 'value', doc.attr('a')
|
782
|
-
assert_equal 'value', doc.attr('a2')
|
783
|
-
|
784
|
-
output = doc.convert
|
785
|
-
assert_includes output, 'value == value'
|
786
|
-
assert_includes output, '2010-01-01 == 2010-01-01'
|
787
|
-
end
|
788
|
-
|
789
|
-
test 'should warn if unterminated block comment is detected in document header' do
|
790
|
-
input = <<-EOS
|
791
|
-
= Document Title
|
792
|
-
:foo: bar
|
793
|
-
////
|
794
|
-
:hey: there
|
795
|
-
|
796
|
-
content
|
797
|
-
EOS
|
798
|
-
doc = document_from_string input
|
799
|
-
assert_nil doc.attr('hey')
|
800
|
-
assert_message @logger, :WARN, '<stdin>: line 3: unterminated comment block', Hash
|
801
|
-
end
|
802
|
-
|
803
|
-
test 'substitutes inside block title' do
|
804
|
-
input = <<-EOS
|
805
|
-
:gem_name: asciidoctor
|
806
|
-
|
807
|
-
.Require the +{gem_name}+ gem
|
808
|
-
To use {gem_name}, the first thing to do is to import it in your Ruby source file.
|
809
|
-
EOS
|
810
|
-
output = convert_string_to_embedded input, :attributes => {'compat-mode' => ''}
|
811
|
-
assert_xpath '//*[@class="title"]/code[text()="asciidoctor"]', output, 1
|
812
|
-
|
813
|
-
input = <<-EOS
|
814
|
-
:gem_name: asciidoctor
|
815
|
-
|
816
|
-
.Require the `{gem_name}` gem
|
817
|
-
To use {gem_name}, the first thing to do is to import it in your Ruby source file.
|
818
|
-
EOS
|
819
|
-
output = convert_string_to_embedded input
|
820
|
-
assert_xpath '//*[@class="title"]/code[text()="asciidoctor"]', output, 1
|
821
|
-
end
|
822
|
-
|
823
|
-
test 'sets attribute until it is deleted' do
|
824
|
-
input = <<-EOS
|
825
|
-
:foo: bar
|
826
|
-
|
827
|
-
Crossing the {foo}.
|
828
|
-
|
829
|
-
:foo!:
|
830
|
-
|
831
|
-
Belly up to the {foo}.
|
832
|
-
EOS
|
833
|
-
output = convert_string_to_embedded input
|
834
|
-
assert_xpath '//p[text()="Crossing the bar."]', output, 1
|
835
|
-
assert_xpath '//p[text()="Belly up to the bar."]', output, 0
|
836
|
-
end
|
837
|
-
|
838
|
-
test 'should allow compat-mode to be set and unset in middle of document' do
|
839
|
-
input = <<-EOS
|
840
|
-
:foo: bar
|
841
|
-
|
842
|
-
[[paragraph-a]]
|
843
|
-
`{foo}`
|
844
|
-
|
845
|
-
:compat-mode!:
|
846
|
-
|
847
|
-
[[paragraph-b]]
|
848
|
-
`{foo}`
|
849
|
-
|
850
|
-
:compat-mode:
|
851
|
-
|
852
|
-
[[paragraph-c]]
|
853
|
-
`{foo}`
|
854
|
-
EOS
|
855
|
-
|
856
|
-
result = convert_string_to_embedded input, :attributes => {'compat-mode' => '@'}
|
857
|
-
assert_xpath '/*[@id="paragraph-a"]//code[text()="{foo}"]', result, 1
|
858
|
-
assert_xpath '/*[@id="paragraph-b"]//code[text()="bar"]', result, 1
|
859
|
-
assert_xpath '/*[@id="paragraph-c"]//code[text()="{foo}"]', result, 1
|
860
|
-
end
|
861
|
-
|
862
|
-
test 'does not disturb attribute-looking things escaped with backslash' do
|
863
|
-
html = convert_string(":foo: bar\nThis is a \\{foo} day.")
|
864
|
-
result = Nokogiri::HTML(html)
|
865
|
-
assert_equal 'This is a {foo} day.', result.css('p').first.content.strip
|
866
|
-
end
|
867
|
-
|
868
|
-
test 'does not disturb attribute-looking things escaped with literals' do
|
869
|
-
html = convert_string(":foo: bar\nThis is a +++{foo}+++ day.")
|
870
|
-
result = Nokogiri::HTML(html)
|
871
|
-
assert_equal 'This is a {foo} day.', result.css('p').first.content.strip
|
872
|
-
end
|
873
|
-
|
874
|
-
test 'does not substitute attributes inside listing blocks' do
|
875
|
-
input = <<-EOS
|
876
|
-
:forecast: snow
|
877
|
-
|
878
|
-
----
|
879
|
-
puts 'The forecast for today is {forecast}'
|
880
|
-
----
|
881
|
-
EOS
|
882
|
-
output = convert_string(input)
|
883
|
-
assert_match(/\{forecast\}/, output)
|
884
|
-
end
|
885
|
-
|
886
|
-
test 'does not substitute attributes inside literal blocks' do
|
887
|
-
input = <<-EOS
|
888
|
-
:foo: bar
|
889
|
-
|
890
|
-
....
|
891
|
-
You insert the text {foo} to expand the value
|
892
|
-
of the attribute named foo in your document.
|
893
|
-
....
|
894
|
-
EOS
|
895
|
-
output = convert_string(input)
|
896
|
-
assert_match(/\{foo\}/, output)
|
897
|
-
end
|
898
|
-
|
899
|
-
test 'does not show docdir and shows relative docfile if safe mode is SERVER or greater' do
|
900
|
-
input = <<-EOS
|
901
|
-
* docdir: {docdir}
|
902
|
-
* docfile: {docfile}
|
903
|
-
EOS
|
904
|
-
|
905
|
-
docdir = Dir.pwd
|
906
|
-
docfile = File.join(docdir, 'sample.asciidoc')
|
907
|
-
output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SERVER, :attributes => {'docdir' => docdir, 'docfile' => docfile}
|
908
|
-
assert_xpath '//li[1]/p[text()="docdir: "]', output, 1
|
909
|
-
assert_xpath '//li[2]/p[text()="docfile: sample.asciidoc"]', output, 1
|
910
|
-
end
|
911
|
-
|
912
|
-
test 'shows absolute docdir and docfile paths if safe mode is less than SERVER' do
|
913
|
-
input = <<-EOS
|
914
|
-
* docdir: {docdir}
|
915
|
-
* docfile: {docfile}
|
916
|
-
EOS
|
917
|
-
|
918
|
-
docdir = Dir.pwd
|
919
|
-
docfile = File.join(docdir, 'sample.asciidoc')
|
920
|
-
output = convert_string_to_embedded input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => docdir, 'docfile' => docfile}
|
921
|
-
assert_xpath %(//li[1]/p[text()="docdir: #{docdir}"]), output, 1
|
922
|
-
assert_xpath %(//li[2]/p[text()="docfile: #{docfile}"]), output, 1
|
923
|
-
end
|
924
|
-
|
925
|
-
test 'assigns attribute defined in attribute reference with set prefix and value' do
|
926
|
-
input = '{set:foo:bar}{foo}'
|
927
|
-
output = convert_string_to_embedded input
|
928
|
-
assert_xpath '//p', output, 1
|
929
|
-
assert_xpath '//p[text()="bar"]', output, 1
|
930
|
-
end
|
931
|
-
|
932
|
-
test 'assigns attribute defined in attribute reference with set prefix and no value' do
|
933
|
-
input = "{set:foo}\n{foo}yes"
|
934
|
-
output = convert_string_to_embedded input
|
935
|
-
assert_xpath '//p', output, 1
|
936
|
-
assert_xpath '//p[normalize-space(text())="yes"]', output, 1
|
937
|
-
end
|
938
|
-
|
939
|
-
test 'assigns attribute defined in attribute reference with set prefix and empty value' do
|
940
|
-
input = "{set:foo:}\n{foo}yes"
|
941
|
-
output = convert_string_to_embedded input
|
942
|
-
assert_xpath '//p', output, 1
|
943
|
-
assert_xpath '//p[normalize-space(text())="yes"]', output, 1
|
944
|
-
end
|
945
|
-
|
946
|
-
test 'unassigns attribute defined in attribute reference with set prefix' do
|
947
|
-
input = <<-EOS
|
948
|
-
:attribute-missing: drop-line
|
949
|
-
:foo:
|
950
|
-
|
951
|
-
{set:foo!}
|
952
|
-
{foo}yes
|
953
|
-
EOS
|
954
|
-
output = convert_string_to_embedded input
|
955
|
-
assert_xpath '//p', output, 1
|
956
|
-
assert_xpath '//p/child::text()', output, 0
|
957
|
-
end
|
958
|
-
end
|
959
|
-
|
960
|
-
context "Intrinsic attributes" do
|
961
|
-
|
962
|
-
test "substitute intrinsics" do
|
963
|
-
Asciidoctor::INTRINSIC_ATTRIBUTES.each_pair do |key, value|
|
964
|
-
html = convert_string("Look, a {#{key}} is here")
|
965
|
-
# can't use Nokogiri because it interprets the HTML entities and we can't match them
|
966
|
-
assert_match(/Look, a #{Regexp.escape(value)} is here/, html)
|
967
|
-
end
|
968
|
-
end
|
969
|
-
|
970
|
-
test "don't escape intrinsic substitutions" do
|
971
|
-
html = convert_string('happy{nbsp}together')
|
972
|
-
assert_match(/happy together/, html)
|
973
|
-
end
|
974
|
-
|
975
|
-
test "escape special characters" do
|
976
|
-
html = convert_string('<node>&</node>')
|
977
|
-
assert_match(/<node>&<\/node>/, html)
|
978
|
-
end
|
979
|
-
|
980
|
-
test 'creates counter' do
|
981
|
-
input = <<-EOS
|
982
|
-
{counter:mycounter}
|
983
|
-
EOS
|
984
|
-
|
985
|
-
doc = document_from_string input
|
986
|
-
output = doc.convert
|
987
|
-
assert_equal 1, doc.attributes['mycounter']
|
988
|
-
assert_xpath '//p[text()="1"]', output, 1
|
989
|
-
end
|
990
|
-
|
991
|
-
test 'creates counter silently' do
|
992
|
-
input = <<-EOS
|
993
|
-
{counter2:mycounter}
|
994
|
-
EOS
|
995
|
-
|
996
|
-
doc = document_from_string input
|
997
|
-
output = doc.convert
|
998
|
-
assert_equal 1, doc.attributes['mycounter']
|
999
|
-
assert_xpath '//p[text()="1"]', output, 0
|
1000
|
-
end
|
1001
|
-
|
1002
|
-
test 'creates counter with numeric seed value' do
|
1003
|
-
input = <<-EOS
|
1004
|
-
{counter2:mycounter:10}
|
1005
|
-
EOS
|
1006
|
-
|
1007
|
-
doc = document_from_string input
|
1008
|
-
doc.convert
|
1009
|
-
assert_equal 10, doc.attributes['mycounter']
|
1010
|
-
end
|
1011
|
-
|
1012
|
-
test 'creates counter with character seed value' do
|
1013
|
-
input = <<-EOS
|
1014
|
-
{counter2:mycounter:A}
|
1015
|
-
EOS
|
1016
|
-
|
1017
|
-
doc = document_from_string input
|
1018
|
-
doc.convert
|
1019
|
-
assert_equal 'A', doc.attributes['mycounter']
|
1020
|
-
end
|
1021
|
-
|
1022
|
-
test 'increments counter with numeric value' do
|
1023
|
-
input = <<-EOS
|
1024
|
-
:mycounter: 1
|
1025
|
-
|
1026
|
-
{counter:mycounter}
|
1027
|
-
|
1028
|
-
{mycounter}
|
1029
|
-
EOS
|
1030
|
-
|
1031
|
-
doc = document_from_string input
|
1032
|
-
output = doc.convert
|
1033
|
-
assert_equal 2, doc.attributes['mycounter']
|
1034
|
-
assert_xpath '//p[text()="2"]', output, 2
|
1035
|
-
end
|
1036
|
-
|
1037
|
-
test 'increments counter with character value' do
|
1038
|
-
input = <<-EOS
|
1039
|
-
:mycounter: @
|
1040
|
-
|
1041
|
-
{counter:mycounter}
|
1042
|
-
|
1043
|
-
{mycounter}
|
1044
|
-
EOS
|
1045
|
-
|
1046
|
-
doc = document_from_string input
|
1047
|
-
output = doc.convert
|
1048
|
-
assert_equal 'A', doc.attributes['mycounter']
|
1049
|
-
assert_xpath '//p[text()="A"]', output, 2
|
1050
|
-
end
|
1051
|
-
|
1052
|
-
test 'counter uses 0 as seed value if seed attribute is nil' do
|
1053
|
-
input = <<-EOS
|
1054
|
-
:mycounter:
|
1055
|
-
|
1056
|
-
{counter:mycounter}
|
1057
|
-
|
1058
|
-
{mycounter}
|
1059
|
-
EOS
|
1060
|
-
|
1061
|
-
doc = document_from_string input
|
1062
|
-
output = doc.convert :header_footer => false
|
1063
|
-
assert_equal 1, doc.attributes['mycounter']
|
1064
|
-
assert_xpath '//p[text()="1"]', output, 2
|
1065
|
-
end
|
1066
|
-
|
1067
|
-
test 'counter value can be reset by attribute entry' do
|
1068
|
-
input = <<-EOS
|
1069
|
-
:mycounter:
|
1070
|
-
|
1071
|
-
before: {counter:mycounter} {counter:mycounter} {counter:mycounter}
|
1072
|
-
|
1073
|
-
:mycounter!:
|
1074
|
-
|
1075
|
-
after: {counter:mycounter}
|
1076
|
-
EOS
|
1077
|
-
|
1078
|
-
doc = document_from_string input
|
1079
|
-
output = doc.convert :header_footer => false
|
1080
|
-
assert_equal 1, doc.attributes['mycounter']
|
1081
|
-
assert_xpath '//p[text()="before: 1 2 3"]', output, 1
|
1082
|
-
assert_xpath '//p[text()="after: 1"]', output, 1
|
1083
|
-
end
|
1084
|
-
|
1085
|
-
test 'nested document should use counter from parent document' do
|
1086
|
-
input = <<-EOS
|
1087
|
-
.Title for Foo
|
1088
|
-
image::foo.jpg[]
|
1089
|
-
|
1090
|
-
[cols="2*a"]
|
1091
|
-
|===
|
1092
|
-
|
|
1093
|
-
.Title for Bar
|
1094
|
-
image::bar.jpg[]
|
1095
|
-
|
1096
|
-
|
|
1097
|
-
.Title for Baz
|
1098
|
-
image::baz.jpg[]
|
1099
|
-
|===
|
1100
|
-
|
1101
|
-
.Title for Qux
|
1102
|
-
image::qux.jpg[]
|
1103
|
-
EOS
|
1104
|
-
|
1105
|
-
output = convert_string_to_embedded input
|
1106
|
-
assert_xpath '//div[@class="title"]', output, 4
|
1107
|
-
assert_xpath '//div[@class="title"][text() = "Figure 1. Title for Foo"]', output, 1
|
1108
|
-
assert_xpath '//div[@class="title"][text() = "Figure 2. Title for Bar"]', output, 1
|
1109
|
-
assert_xpath '//div[@class="title"][text() = "Figure 3. Title for Baz"]', output, 1
|
1110
|
-
assert_xpath '//div[@class="title"][text() = "Figure 4. Title for Qux"]', output, 1
|
1111
|
-
end
|
1112
|
-
end
|
1113
|
-
|
1114
|
-
context 'Block attributes' do
|
1115
|
-
test 'parses attribute names as name token' do
|
1116
|
-
input = <<-EOS
|
1117
|
-
[normal,foo="bar",_foo="_bar",foo1="bar1",foo-foo="bar-bar",foo.foo="bar.bar"]
|
1118
|
-
content
|
1119
|
-
EOS
|
1120
|
-
|
1121
|
-
block = block_from_string input
|
1122
|
-
assert_equal 'bar', block.attr('foo')
|
1123
|
-
assert_equal '_bar', block.attr('_foo')
|
1124
|
-
assert_equal 'bar1', block.attr('foo1')
|
1125
|
-
assert_equal 'bar-bar', block.attr('foo-foo')
|
1126
|
-
assert_equal 'bar.bar', block.attr('foo.foo')
|
1127
|
-
end
|
1128
|
-
|
1129
|
-
test 'positional attributes assigned to block' do
|
1130
|
-
input = <<-EOS
|
1131
|
-
[quote, author, source]
|
1132
|
-
____
|
1133
|
-
A famous quote.
|
1134
|
-
____
|
1135
|
-
EOS
|
1136
|
-
doc = document_from_string(input)
|
1137
|
-
qb = doc.blocks.first
|
1138
|
-
assert_equal 'quote', qb.style
|
1139
|
-
assert_equal 'author', qb.attr('attribution')
|
1140
|
-
assert_equal 'author', qb.attr(:attribution)
|
1141
|
-
assert_equal 'author', qb.attributes['attribution']
|
1142
|
-
assert_equal 'source', qb.attributes['citetitle']
|
1143
|
-
end
|
1144
|
-
|
1145
|
-
test 'normal substitutions are performed on single-quoted positional attribute' do
|
1146
|
-
input = <<-EOS
|
1147
|
-
[quote, author, 'http://wikipedia.org[source]']
|
1148
|
-
____
|
1149
|
-
A famous quote.
|
1150
|
-
____
|
1151
|
-
EOS
|
1152
|
-
doc = document_from_string(input)
|
1153
|
-
qb = doc.blocks.first
|
1154
|
-
assert_equal 'quote', qb.style
|
1155
|
-
assert_equal 'author', qb.attr('attribution')
|
1156
|
-
assert_equal 'author', qb.attr(:attribution)
|
1157
|
-
assert_equal 'author', qb.attributes['attribution']
|
1158
|
-
assert_equal '<a href="http://wikipedia.org">source</a>', qb.attributes['citetitle']
|
1159
|
-
end
|
1160
|
-
|
1161
|
-
test 'normal substitutions are performed on single-quoted named attribute' do
|
1162
|
-
input = <<-EOS
|
1163
|
-
[quote, author, citetitle='http://wikipedia.org[source]']
|
1164
|
-
____
|
1165
|
-
A famous quote.
|
1166
|
-
____
|
1167
|
-
EOS
|
1168
|
-
doc = document_from_string(input)
|
1169
|
-
qb = doc.blocks.first
|
1170
|
-
assert_equal 'quote', qb.style
|
1171
|
-
assert_equal 'author', qb.attr('attribution')
|
1172
|
-
assert_equal 'author', qb.attr(:attribution)
|
1173
|
-
assert_equal 'author', qb.attributes['attribution']
|
1174
|
-
assert_equal '<a href="http://wikipedia.org">source</a>', qb.attributes['citetitle']
|
1175
|
-
end
|
1176
|
-
|
1177
|
-
test 'normal substitutions are performed once on single-quoted named title attribute' do
|
1178
|
-
input = <<-EOS
|
1179
|
-
[title='*title*']
|
1180
|
-
content
|
1181
|
-
EOS
|
1182
|
-
output = convert_string_to_embedded input
|
1183
|
-
assert_xpath '//*[@class="title"]/strong[text()="title"]', output, 1
|
1184
|
-
end
|
1185
|
-
|
1186
|
-
test 'attribute list may not begin with space' do
|
1187
|
-
input = <<-EOS
|
1188
|
-
[ quote]
|
1189
|
-
____
|
1190
|
-
A famous quote.
|
1191
|
-
____
|
1192
|
-
EOS
|
1193
|
-
|
1194
|
-
doc = document_from_string input
|
1195
|
-
b1 = doc.blocks.first
|
1196
|
-
assert_equal ['[ quote]'], b1.lines
|
1197
|
-
end
|
1198
|
-
|
1199
|
-
test 'attribute list may begin with comma' do
|
1200
|
-
input = <<-EOS
|
1201
|
-
[, author, source]
|
1202
|
-
____
|
1203
|
-
A famous quote.
|
1204
|
-
____
|
1205
|
-
EOS
|
1206
|
-
|
1207
|
-
doc = document_from_string input
|
1208
|
-
qb = doc.blocks.first
|
1209
|
-
assert_equal 'quote', qb.style
|
1210
|
-
assert_equal 'author', qb.attributes['attribution']
|
1211
|
-
assert_equal 'source', qb.attributes['citetitle']
|
1212
|
-
end
|
1213
|
-
|
1214
|
-
test 'first attribute in list may be double quoted' do
|
1215
|
-
input = <<-EOS
|
1216
|
-
["quote", "author", "source", role="famous"]
|
1217
|
-
____
|
1218
|
-
A famous quote.
|
1219
|
-
____
|
1220
|
-
EOS
|
1221
|
-
|
1222
|
-
doc = document_from_string input
|
1223
|
-
qb = doc.blocks.first
|
1224
|
-
assert_equal 'quote', qb.style
|
1225
|
-
assert_equal 'author', qb.attributes['attribution']
|
1226
|
-
assert_equal 'source', qb.attributes['citetitle']
|
1227
|
-
assert_equal 'famous', qb.attributes['role']
|
1228
|
-
end
|
1229
|
-
|
1230
|
-
test 'first attribute in list may be single quoted' do
|
1231
|
-
input = <<-EOS
|
1232
|
-
['quote', 'author', 'source', role='famous']
|
1233
|
-
____
|
1234
|
-
A famous quote.
|
1235
|
-
____
|
1236
|
-
EOS
|
1237
|
-
|
1238
|
-
doc = document_from_string input
|
1239
|
-
qb = doc.blocks.first
|
1240
|
-
assert_equal 'quote', qb.style
|
1241
|
-
assert_equal 'author', qb.attributes['attribution']
|
1242
|
-
assert_equal 'source', qb.attributes['citetitle']
|
1243
|
-
assert_equal 'famous', qb.attributes['role']
|
1244
|
-
end
|
1245
|
-
|
1246
|
-
test 'attribute with value None without quotes is ignored' do
|
1247
|
-
input = <<-EOS
|
1248
|
-
[id=None]
|
1249
|
-
paragraph
|
1250
|
-
EOS
|
1251
|
-
|
1252
|
-
doc = document_from_string input
|
1253
|
-
para = doc.blocks.first
|
1254
|
-
refute para.attributes.has_key?('id')
|
1255
|
-
end
|
1256
|
-
|
1257
|
-
test 'role? returns true if role is assigned' do
|
1258
|
-
input = <<-EOS
|
1259
|
-
[role="lead"]
|
1260
|
-
A paragraph
|
1261
|
-
EOS
|
1262
|
-
|
1263
|
-
doc = document_from_string input
|
1264
|
-
p = doc.blocks.first
|
1265
|
-
assert p.role?
|
1266
|
-
end
|
1267
|
-
|
1268
|
-
test 'role? can check for exact role name match' do
|
1269
|
-
input = <<-EOS
|
1270
|
-
[role="lead"]
|
1271
|
-
A paragraph
|
1272
|
-
EOS
|
1273
|
-
|
1274
|
-
doc = document_from_string input
|
1275
|
-
p = doc.blocks.first
|
1276
|
-
assert p.role?('lead')
|
1277
|
-
p2 = doc.blocks.last
|
1278
|
-
refute p2.role?('final')
|
1279
|
-
end
|
1280
|
-
|
1281
|
-
test 'has_role? can check for precense of role name' do
|
1282
|
-
input = <<-EOS
|
1283
|
-
[role="lead abstract"]
|
1284
|
-
A paragraph
|
1285
|
-
EOS
|
1286
|
-
|
1287
|
-
doc = document_from_string input
|
1288
|
-
p = doc.blocks.first
|
1289
|
-
refute p.role?('lead')
|
1290
|
-
assert p.has_role?('lead')
|
1291
|
-
end
|
1292
|
-
|
1293
|
-
test 'roles returns array of role names' do
|
1294
|
-
input = <<-EOS
|
1295
|
-
[role="story lead"]
|
1296
|
-
A paragraph
|
1297
|
-
EOS
|
1298
|
-
|
1299
|
-
doc = document_from_string input
|
1300
|
-
p = doc.blocks.first
|
1301
|
-
assert_equal ['story', 'lead'], p.roles
|
1302
|
-
end
|
1303
|
-
|
1304
|
-
test 'roles returns empty array if role attribute is not set' do
|
1305
|
-
input = <<-EOS
|
1306
|
-
A paragraph
|
1307
|
-
EOS
|
1308
|
-
|
1309
|
-
doc = document_from_string input
|
1310
|
-
p = doc.blocks.first
|
1311
|
-
assert_equal [], p.roles
|
1312
|
-
end
|
1313
|
-
|
1314
|
-
test "Attribute substitutions are performed on attribute list before parsing attributes" do
|
1315
|
-
input = <<-EOS
|
1316
|
-
:lead: role="lead"
|
1317
|
-
|
1318
|
-
[{lead}]
|
1319
|
-
A paragraph
|
1320
|
-
EOS
|
1321
|
-
doc = document_from_string(input)
|
1322
|
-
para = doc.blocks.first
|
1323
|
-
assert_equal 'lead', para.attributes['role']
|
1324
|
-
end
|
1325
|
-
|
1326
|
-
test 'id, role and options attributes can be specified on block style using shorthand syntax' do
|
1327
|
-
input = <<-EOS
|
1328
|
-
[literal#first.lead%step]
|
1329
|
-
A literal paragraph.
|
1330
|
-
EOS
|
1331
|
-
doc = document_from_string(input)
|
1332
|
-
para = doc.blocks.first
|
1333
|
-
assert_equal :literal, para.context
|
1334
|
-
assert_equal 'first', para.attributes['id']
|
1335
|
-
assert_equal 'lead', para.attributes['role']
|
1336
|
-
assert_equal 'step', para.attributes['options']
|
1337
|
-
assert para.attributes.has_key?('step-option')
|
1338
|
-
end
|
1339
|
-
|
1340
|
-
test 'id, role and options attributes can be specified using shorthand syntax on block style using multiple block attribute lines' do
|
1341
|
-
input = <<-EOS
|
1342
|
-
[literal]
|
1343
|
-
[#first]
|
1344
|
-
[.lead]
|
1345
|
-
[%step]
|
1346
|
-
A literal paragraph.
|
1347
|
-
EOS
|
1348
|
-
doc = document_from_string(input)
|
1349
|
-
para = doc.blocks.first
|
1350
|
-
assert_equal :literal, para.context
|
1351
|
-
assert_equal 'first', para.attributes['id']
|
1352
|
-
assert_equal 'lead', para.attributes['role']
|
1353
|
-
assert_equal 'step', para.attributes['options']
|
1354
|
-
assert para.attributes.has_key?('step-option')
|
1355
|
-
end
|
1356
|
-
|
1357
|
-
test 'multiple roles and options can be specified in block style using shorthand syntax' do
|
1358
|
-
input = <<-EOS
|
1359
|
-
[.role1%option1.role2%option2]
|
1360
|
-
Text
|
1361
|
-
EOS
|
1362
|
-
|
1363
|
-
doc = document_from_string input
|
1364
|
-
para = doc.blocks.first
|
1365
|
-
assert_equal 'role1 role2', para.attributes['role']
|
1366
|
-
assert_equal 'option1,option2', para.attributes['options']
|
1367
|
-
assert para.attributes.has_key?('option1-option')
|
1368
|
-
assert para.attributes.has_key?('option2-option')
|
1369
|
-
end
|
1370
|
-
|
1371
|
-
test 'options specified using shorthand syntax on block style across multiple lines should be additive' do
|
1372
|
-
input = <<-EOS
|
1373
|
-
[%option1]
|
1374
|
-
[%option2]
|
1375
|
-
Text
|
1376
|
-
EOS
|
1377
|
-
|
1378
|
-
doc = document_from_string input
|
1379
|
-
para = doc.blocks.first
|
1380
|
-
assert_equal 'option1,option2', para.attributes['options']
|
1381
|
-
assert para.attributes.has_key?('option1-option')
|
1382
|
-
assert para.attributes.has_key?('option2-option')
|
1383
|
-
end
|
1384
|
-
|
1385
|
-
test 'roles specified using shorthand syntax on block style across multiple lines should be additive' do
|
1386
|
-
input = <<-EOS
|
1387
|
-
[.role1]
|
1388
|
-
[.role2.role3]
|
1389
|
-
Text
|
1390
|
-
EOS
|
1391
|
-
|
1392
|
-
doc = document_from_string input
|
1393
|
-
para = doc.blocks.first
|
1394
|
-
assert_equal 'role1 role2 role3', para.attributes['role']
|
1395
|
-
end
|
1396
|
-
|
1397
|
-
test 'setting a role using the role attribute replaces any existing roles' do
|
1398
|
-
input = <<-EOS
|
1399
|
-
[.role1]
|
1400
|
-
[role=role2]
|
1401
|
-
[.role3]
|
1402
|
-
Text
|
1403
|
-
EOS
|
1404
|
-
|
1405
|
-
doc = document_from_string input
|
1406
|
-
para = doc.blocks.first
|
1407
|
-
assert_equal 'role2 role3', para.attributes['role']
|
1408
|
-
end
|
1409
|
-
|
1410
|
-
test 'setting a role using the shorthand syntax on block style should not clear the ID' do
|
1411
|
-
input = <<-EOS
|
1412
|
-
[#id]
|
1413
|
-
[.role]
|
1414
|
-
Text
|
1415
|
-
EOS
|
1416
|
-
|
1417
|
-
doc = document_from_string input
|
1418
|
-
para = doc.blocks.first
|
1419
|
-
assert_equal 'id', para.id
|
1420
|
-
assert_equal 'role', para.role
|
1421
|
-
end
|
1422
|
-
|
1423
|
-
test 'a role can be added using add_role when the node has no roles' do
|
1424
|
-
input = <<-EOS
|
1425
|
-
A normal paragraph
|
1426
|
-
EOS
|
1427
|
-
doc = document_from_string(input)
|
1428
|
-
para = doc.blocks.first
|
1429
|
-
res = para.add_role 'role1'
|
1430
|
-
assert res
|
1431
|
-
assert_equal 'role1', para.attributes['role']
|
1432
|
-
assert para.has_role? 'role1'
|
1433
|
-
end
|
1434
|
-
|
1435
|
-
test 'a role can be added using add_role when the node already has a role' do
|
1436
|
-
input = <<-EOS
|
1437
|
-
[.role1]
|
1438
|
-
A normal paragraph
|
1439
|
-
EOS
|
1440
|
-
doc = document_from_string(input)
|
1441
|
-
para = doc.blocks.first
|
1442
|
-
res = para.add_role 'role2'
|
1443
|
-
assert res
|
1444
|
-
assert_equal 'role1 role2', para.attributes['role']
|
1445
|
-
assert para.has_role? 'role1'
|
1446
|
-
assert para.has_role? 'role2'
|
1447
|
-
end
|
1448
|
-
|
1449
|
-
test 'a role is not added using add_role if the node already has that role' do
|
1450
|
-
input = <<-EOS
|
1451
|
-
[.role1]
|
1452
|
-
A normal paragraph
|
1453
|
-
EOS
|
1454
|
-
doc = document_from_string(input)
|
1455
|
-
para = doc.blocks.first
|
1456
|
-
res = para.add_role 'role1'
|
1457
|
-
refute res
|
1458
|
-
assert_equal 'role1', para.attributes['role']
|
1459
|
-
assert para.has_role? 'role1'
|
1460
|
-
end
|
1461
|
-
|
1462
|
-
test 'an existing role can be removed using remove_role' do
|
1463
|
-
input = <<-EOS
|
1464
|
-
[.role1.role2]
|
1465
|
-
A normal paragraph
|
1466
|
-
EOS
|
1467
|
-
doc = document_from_string(input)
|
1468
|
-
para = doc.blocks.first
|
1469
|
-
res = para.remove_role 'role1'
|
1470
|
-
assert res
|
1471
|
-
assert_equal 'role2', para.attributes['role']
|
1472
|
-
assert para.has_role? 'role2'
|
1473
|
-
refute para.has_role?('role1')
|
1474
|
-
end
|
1475
|
-
|
1476
|
-
test 'roles are removed when last role is removed using remove_role' do
|
1477
|
-
input = <<-EOS
|
1478
|
-
[.role1]
|
1479
|
-
A normal paragraph
|
1480
|
-
EOS
|
1481
|
-
doc = document_from_string(input)
|
1482
|
-
para = doc.blocks.first
|
1483
|
-
res = para.remove_role 'role1'
|
1484
|
-
assert res
|
1485
|
-
refute para.role?
|
1486
|
-
assert_nil para.attributes['role']
|
1487
|
-
refute para.has_role? 'role1'
|
1488
|
-
end
|
1489
|
-
|
1490
|
-
test 'roles are not changed when a non-existent role is removed using remove_role' do
|
1491
|
-
input = <<-EOS
|
1492
|
-
[.role1]
|
1493
|
-
A normal paragraph
|
1494
|
-
EOS
|
1495
|
-
doc = document_from_string(input)
|
1496
|
-
para = doc.blocks.first
|
1497
|
-
res = para.remove_role 'role2'
|
1498
|
-
refute res
|
1499
|
-
assert_equal 'role1', para.attributes['role']
|
1500
|
-
assert para.has_role? 'role1'
|
1501
|
-
refute para.has_role?('role2')
|
1502
|
-
end
|
1503
|
-
|
1504
|
-
test 'roles are not changed when using remove_role if the node has no roles' do
|
1505
|
-
input = <<-EOS
|
1506
|
-
A normal paragraph
|
1507
|
-
EOS
|
1508
|
-
doc = document_from_string(input)
|
1509
|
-
para = doc.blocks.first
|
1510
|
-
res = para.remove_role 'role1'
|
1511
|
-
refute res
|
1512
|
-
assert_nil para.attributes['role']
|
1513
|
-
refute para.has_role?('role1')
|
1514
|
-
end
|
1515
|
-
|
1516
|
-
test 'option can be specified in first position of block style using shorthand syntax' do
|
1517
|
-
input = <<-EOS
|
1518
|
-
[%interactive]
|
1519
|
-
- [x] checked
|
1520
|
-
EOS
|
1521
|
-
|
1522
|
-
doc = document_from_string input
|
1523
|
-
list = doc.blocks.first
|
1524
|
-
assert_equal 'interactive', list.attributes['options']
|
1525
|
-
assert list.attributes.has_key?('interactive-option')
|
1526
|
-
end
|
1527
|
-
|
1528
|
-
test 'id and role attributes can be specified on section style using shorthand syntax' do
|
1529
|
-
input = <<-EOS
|
1530
|
-
[dedication#dedication.small]
|
1531
|
-
== Section
|
1532
|
-
Content.
|
1533
|
-
EOS
|
1534
|
-
output = convert_string_to_embedded input
|
1535
|
-
assert_xpath '/div[@class="sect1 small"]', output, 1
|
1536
|
-
assert_xpath '/div[@class="sect1 small"]/h2[@id="dedication"]', output, 1
|
1537
|
-
end
|
1538
|
-
|
1539
|
-
test 'id attribute specified using shorthand syntax should not create a special section' do
|
1540
|
-
input = <<-EOS
|
1541
|
-
[#idname]
|
1542
|
-
== Section
|
1543
|
-
|
1544
|
-
content
|
1545
|
-
EOS
|
1546
|
-
|
1547
|
-
doc = document_from_string input, :backend => 'docbook45'
|
1548
|
-
section = doc.blocks[0]
|
1549
|
-
refute_nil section
|
1550
|
-
assert_equal :section, section.context
|
1551
|
-
refute section.special
|
1552
|
-
output = doc.convert
|
1553
|
-
assert_css 'section', output, 1
|
1554
|
-
assert_css 'section#idname', output, 1
|
1555
|
-
end
|
1556
|
-
|
1557
|
-
test "Block attributes are additive" do
|
1558
|
-
input = <<-EOS
|
1559
|
-
[id='foo']
|
1560
|
-
[role='lead']
|
1561
|
-
A paragraph.
|
1562
|
-
EOS
|
1563
|
-
doc = document_from_string(input)
|
1564
|
-
para = doc.blocks.first
|
1565
|
-
assert_equal 'foo', para.id
|
1566
|
-
assert_equal 'lead', para.attributes['role']
|
1567
|
-
end
|
1568
|
-
|
1569
|
-
test "Last wins for id attribute" do
|
1570
|
-
input = <<-EOS
|
1571
|
-
[[bar]]
|
1572
|
-
[[foo]]
|
1573
|
-
== Section
|
1574
|
-
|
1575
|
-
paragraph
|
1576
|
-
|
1577
|
-
[[baz]]
|
1578
|
-
[id='coolio']
|
1579
|
-
=== Section
|
1580
|
-
EOS
|
1581
|
-
doc = document_from_string(input)
|
1582
|
-
sec = doc.first_section
|
1583
|
-
assert_equal 'foo', sec.id
|
1584
|
-
subsec = sec.blocks.last
|
1585
|
-
assert_equal 'coolio', subsec.id
|
1586
|
-
end
|
1587
|
-
|
1588
|
-
test "trailing block attributes transfer to the following section" do
|
1589
|
-
input = <<-EOS
|
1590
|
-
[[one]]
|
1591
|
-
|
1592
|
-
== Section One
|
1593
|
-
|
1594
|
-
paragraph
|
1595
|
-
|
1596
|
-
[[sub]]
|
1597
|
-
// try to mess this up!
|
1598
|
-
|
1599
|
-
=== Sub-section
|
1600
|
-
|
1601
|
-
paragraph
|
1602
|
-
|
1603
|
-
[role='classy']
|
1604
|
-
|
1605
|
-
////
|
1606
|
-
block comment
|
1607
|
-
////
|
1608
|
-
|
1609
|
-
== Section Two
|
1610
|
-
|
1611
|
-
content
|
1612
|
-
EOS
|
1613
|
-
doc = document_from_string(input)
|
1614
|
-
section_one = doc.blocks.first
|
1615
|
-
assert_equal 'one', section_one.id
|
1616
|
-
subsection = section_one.blocks.last
|
1617
|
-
assert_equal 'sub', subsection.id
|
1618
|
-
section_two = doc.blocks.last
|
1619
|
-
assert_equal 'classy', section_two.attr(:role)
|
1620
|
-
end
|
1621
|
-
end
|
1622
|
-
|
1623
|
-
end
|