asciidoctor 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of asciidoctor might be problematic. Click here for more details.
- data/README.asciidoc +11 -2
- data/asciidoctor.gemspec +3 -2
- data/lib/asciidoctor.rb +95 -62
- data/lib/asciidoctor/abstract_block.rb +7 -5
- data/lib/asciidoctor/abstract_node.rb +63 -15
- data/lib/asciidoctor/attribute_list.rb +3 -1
- data/lib/asciidoctor/backends/base_template.rb +17 -7
- data/lib/asciidoctor/backends/docbook45.rb +182 -150
- data/lib/asciidoctor/backends/html5.rb +138 -110
- data/lib/asciidoctor/block.rb +21 -18
- data/lib/asciidoctor/callouts.rb +3 -1
- data/lib/asciidoctor/cli/invoker.rb +3 -3
- data/lib/asciidoctor/cli/options.rb +6 -6
- data/lib/asciidoctor/debug.rb +7 -6
- data/lib/asciidoctor/document.rb +197 -25
- data/lib/asciidoctor/errors.rb +1 -1
- data/lib/asciidoctor/helpers.rb +29 -0
- data/lib/asciidoctor/inline.rb +11 -4
- data/lib/asciidoctor/lexer.rb +338 -182
- data/lib/asciidoctor/list_item.rb +14 -12
- data/lib/asciidoctor/reader.rb +423 -206
- data/lib/asciidoctor/renderer.rb +59 -15
- data/lib/asciidoctor/section.rb +7 -4
- data/lib/asciidoctor/substituters.rb +536 -511
- data/lib/asciidoctor/table.rb +473 -472
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +23 -14
- data/man/asciidoctor.ad +13 -7
- data/test/attributes_test.rb +42 -8
- data/test/blocks_test.rb +161 -1
- data/test/document_test.rb +134 -16
- data/test/invoker_test.rb +14 -6
- data/test/lexer_test.rb +45 -18
- data/test/lists_test.rb +79 -0
- data/test/paragraphs_test.rb +9 -1
- data/test/reader_test.rb +456 -19
- data/test/sections_test.rb +19 -0
- data/test/substitutions_test.rb +14 -12
- data/test/tables_test.rb +10 -10
- metadata +3 -5
data/test/invoker_test.rb
CHANGED
@@ -87,10 +87,10 @@ context 'Invoker' do
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
-
test 'should
|
90
|
+
test 'should warn if extra arguments are detected' do
|
91
91
|
redirect_streams do |stdout, stderr|
|
92
92
|
invoker = invoke_cli %w(-o /dev/null extra arguments sample.asciidoc), nil
|
93
|
-
assert_match(/
|
93
|
+
assert_match(/extra arguments detected/, stderr.string)
|
94
94
|
assert_equal 1, invoker.code
|
95
95
|
end
|
96
96
|
end
|
@@ -239,10 +239,18 @@ context 'Invoker' do
|
|
239
239
|
assert_equal Asciidoctor::SafeMode::SAFE, doc.safe
|
240
240
|
end
|
241
241
|
|
242
|
-
test 'should set safe mode to specified level
|
243
|
-
|
244
|
-
|
245
|
-
|
242
|
+
test 'should set safe mode to specified level' do
|
243
|
+
levels = {
|
244
|
+
'unsafe' => Asciidoctor::SafeMode::UNSAFE,
|
245
|
+
'safe' => Asciidoctor::SafeMode::SAFE,
|
246
|
+
'server' => Asciidoctor::SafeMode::SERVER,
|
247
|
+
'secure' => Asciidoctor::SafeMode::SECURE,
|
248
|
+
}
|
249
|
+
levels.each do |name, const|
|
250
|
+
invoker = invoke_cli_to_buffer %W(-S #{name} -o /dev/null)
|
251
|
+
doc = invoker.document
|
252
|
+
assert_equal const, doc.safe
|
253
|
+
end
|
246
254
|
end
|
247
255
|
|
248
256
|
test 'should set eRuby impl if specified' do
|
data/test/lexer_test.rb
CHANGED
@@ -2,7 +2,7 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
context "Lexer" do
|
4
4
|
|
5
|
-
test "
|
5
|
+
test "is_section_title?" do
|
6
6
|
assert Asciidoctor::Lexer.is_section_title?('AsciiDoc Home Page', '==================')
|
7
7
|
assert Asciidoctor::Lexer.is_section_title?('=== AsciiDoc Home Page')
|
8
8
|
end
|
@@ -174,7 +174,7 @@ context "Lexer" do
|
|
174
174
|
assert_equal expected, attributes
|
175
175
|
end
|
176
176
|
|
177
|
-
test "
|
177
|
+
test "parse author first" do
|
178
178
|
metadata, = parse_header_metadata 'Stuart'
|
179
179
|
assert_equal 3, metadata.size
|
180
180
|
assert_equal 'Stuart', metadata['author']
|
@@ -182,7 +182,7 @@ context "Lexer" do
|
|
182
182
|
assert_equal 'S', metadata['authorinitials']
|
183
183
|
end
|
184
184
|
|
185
|
-
test "
|
185
|
+
test "parse author first last" do
|
186
186
|
metadata, = parse_header_metadata 'Yukihiro Matsumoto'
|
187
187
|
assert_equal 4, metadata.size
|
188
188
|
assert_equal 'Yukihiro Matsumoto', metadata['author']
|
@@ -191,7 +191,7 @@ context "Lexer" do
|
|
191
191
|
assert_equal 'YM', metadata['authorinitials']
|
192
192
|
end
|
193
193
|
|
194
|
-
test "
|
194
|
+
test "parse author first middle last" do
|
195
195
|
metadata, = parse_header_metadata 'David Heinemeier Hansson'
|
196
196
|
assert_equal 5, metadata.size
|
197
197
|
assert_equal 'David Heinemeier Hansson', metadata['author']
|
@@ -201,7 +201,7 @@ context "Lexer" do
|
|
201
201
|
assert_equal 'DHH', metadata['authorinitials']
|
202
202
|
end
|
203
203
|
|
204
|
-
test "
|
204
|
+
test "parse author first middle last email" do
|
205
205
|
metadata, = parse_header_metadata 'David Heinemeier Hansson <rails@ruby-lang.org>'
|
206
206
|
assert_equal 6, metadata.size
|
207
207
|
assert_equal 'David Heinemeier Hansson', metadata['author']
|
@@ -212,7 +212,7 @@ context "Lexer" do
|
|
212
212
|
assert_equal 'DHH', metadata['authorinitials']
|
213
213
|
end
|
214
214
|
|
215
|
-
test "
|
215
|
+
test "parse author first email" do
|
216
216
|
metadata, = parse_header_metadata 'Stuart <founder@asciidoc.org>'
|
217
217
|
assert_equal 4, metadata.size
|
218
218
|
assert_equal 'Stuart', metadata['author']
|
@@ -221,7 +221,7 @@ context "Lexer" do
|
|
221
221
|
assert_equal 'S', metadata['authorinitials']
|
222
222
|
end
|
223
223
|
|
224
|
-
test "
|
224
|
+
test "parse author first last email" do
|
225
225
|
metadata, = parse_header_metadata 'Stuart Rackham <founder@asciidoc.org>'
|
226
226
|
assert_equal 5, metadata.size
|
227
227
|
assert_equal 'Stuart Rackham', metadata['author']
|
@@ -231,7 +231,7 @@ context "Lexer" do
|
|
231
231
|
assert_equal 'SR', metadata['authorinitials']
|
232
232
|
end
|
233
233
|
|
234
|
-
test "
|
234
|
+
test "parse author with hyphen" do
|
235
235
|
metadata, = parse_header_metadata 'Tim Berners-Lee <founder@www.org>'
|
236
236
|
assert_equal 5, metadata.size
|
237
237
|
assert_equal 'Tim Berners-Lee', metadata['author']
|
@@ -241,7 +241,7 @@ context "Lexer" do
|
|
241
241
|
assert_equal 'TB', metadata['authorinitials']
|
242
242
|
end
|
243
243
|
|
244
|
-
test "
|
244
|
+
test "parse author with single quote" do
|
245
245
|
metadata, = parse_header_metadata 'Stephen O\'Grady <founder@redmonk.com>'
|
246
246
|
assert_equal 5, metadata.size
|
247
247
|
assert_equal 'Stephen O\'Grady', metadata['author']
|
@@ -262,7 +262,7 @@ context "Lexer" do
|
|
262
262
|
assert_equal 'HWR', metadata['authorinitials']
|
263
263
|
end
|
264
264
|
|
265
|
-
test "
|
265
|
+
test "parse author with underscore" do
|
266
266
|
metadata, = parse_header_metadata 'Tim_E Fella'
|
267
267
|
assert_equal 4, metadata.size
|
268
268
|
assert_equal 'Tim E Fella', metadata['author']
|
@@ -271,7 +271,7 @@ context "Lexer" do
|
|
271
271
|
assert_equal 'TF', metadata['authorinitials']
|
272
272
|
end
|
273
273
|
|
274
|
-
test "
|
274
|
+
test "parse author condenses whitespace" do
|
275
275
|
metadata, = parse_header_metadata ' Stuart Rackham <founder@asciidoc.org>'
|
276
276
|
assert_equal 5, metadata.size
|
277
277
|
assert_equal 'Stuart Rackham', metadata['author']
|
@@ -281,7 +281,7 @@ context "Lexer" do
|
|
281
281
|
assert_equal 'SR', metadata['authorinitials']
|
282
282
|
end
|
283
283
|
|
284
|
-
test "
|
284
|
+
test "parse invalid author line becomes author" do
|
285
285
|
metadata, = parse_header_metadata ' Stuart Rackham, founder of AsciiDoc <founder@asciidoc.org>'
|
286
286
|
assert_equal 3, metadata.size
|
287
287
|
assert_equal 'Stuart Rackham, founder of AsciiDoc <founder@asciidoc.org>', metadata['author']
|
@@ -289,7 +289,7 @@ context "Lexer" do
|
|
289
289
|
assert_equal 'S', metadata['authorinitials']
|
290
290
|
end
|
291
291
|
|
292
|
-
test "
|
292
|
+
test "parse rev number date remark" do
|
293
293
|
metadata, = parse_header_metadata "Ryan Waldron\nv0.0.7, 2013-12-18: The first release you can stand on"
|
294
294
|
assert_equal 7, metadata.size
|
295
295
|
assert_equal '0.0.7', metadata['revnumber']
|
@@ -297,20 +297,39 @@ context "Lexer" do
|
|
297
297
|
assert_equal 'The first release you can stand on', metadata['revremark']
|
298
298
|
end
|
299
299
|
|
300
|
-
test "
|
300
|
+
test "parse rev date" do
|
301
301
|
metadata, = parse_header_metadata "Ryan Waldron\n2013-12-18"
|
302
302
|
assert_equal 5, metadata.size
|
303
303
|
assert_equal '2013-12-18', metadata['revdate']
|
304
304
|
end
|
305
305
|
|
306
|
-
|
306
|
+
# while compliant w/ AsciiDoc, this is just sloppy parsing
|
307
|
+
test "treats arbitrary text on rev line as revdate" do
|
308
|
+
metadata, = parse_header_metadata "Ryan Waldron\nfoobar\n"
|
309
|
+
assert_equal 5, metadata.size
|
310
|
+
assert_equal 'foobar', metadata['revdate']
|
311
|
+
end
|
312
|
+
|
313
|
+
test "parse rev date remark" do
|
307
314
|
metadata, = parse_header_metadata "Ryan Waldron\n2013-12-18: The first release you can stand on"
|
308
315
|
assert_equal 6, metadata.size
|
309
316
|
assert_equal '2013-12-18', metadata['revdate']
|
310
317
|
assert_equal 'The first release you can stand on', metadata['revremark']
|
311
318
|
end
|
312
319
|
|
313
|
-
test "
|
320
|
+
test "should not mistake attribute entry as rev remark" do
|
321
|
+
metadata, = parse_header_metadata "Joe Cool\n:layout: post\n"
|
322
|
+
assert_not_equal 'layout: post', metadata['revremark']
|
323
|
+
assert !metadata.has_key?('revdate')
|
324
|
+
end
|
325
|
+
|
326
|
+
test "parse rev remark only" do
|
327
|
+
metadata, = parse_header_metadata "Joe Cool\n :Must start line with space\n"
|
328
|
+
assert_equal 'Must start line with space', metadata['revremark']
|
329
|
+
assert_equal '', metadata['revdate']
|
330
|
+
end
|
331
|
+
|
332
|
+
test "skip line comments before author" do
|
314
333
|
metadata, = parse_header_metadata "// Asciidoctor\n// release artist\nRyan Waldron"
|
315
334
|
assert_equal 4, metadata.size
|
316
335
|
assert_equal 'Ryan Waldron', metadata['author']
|
@@ -319,7 +338,7 @@ context "Lexer" do
|
|
319
338
|
assert_equal 'RW', metadata['authorinitials']
|
320
339
|
end
|
321
340
|
|
322
|
-
test "
|
341
|
+
test "skip block comment before author" do
|
323
342
|
metadata, = parse_header_metadata "////\nAsciidoctor\nrelease artist\n////\nRyan Waldron"
|
324
343
|
assert_equal 4, metadata.size
|
325
344
|
assert_equal 'Ryan Waldron', metadata['author']
|
@@ -328,7 +347,7 @@ context "Lexer" do
|
|
328
347
|
assert_equal 'RW', metadata['authorinitials']
|
329
348
|
end
|
330
349
|
|
331
|
-
test "
|
350
|
+
test "skip block comment before rev" do
|
332
351
|
metadata, = parse_header_metadata "Ryan Waldron\n////\nAsciidoctor\nrelease info\n////\nv0.0.7, 2013-12-18"
|
333
352
|
assert_equal 6, metadata.size
|
334
353
|
assert_equal 'Ryan Waldron', metadata['author']
|
@@ -336,4 +355,12 @@ context "Lexer" do
|
|
336
355
|
assert_equal '2013-12-18', metadata['revdate']
|
337
356
|
end
|
338
357
|
|
358
|
+
test "attribute entry overrides generated author initials" do
|
359
|
+
blankdoc = Asciidoctor::Document.new
|
360
|
+
reader = Asciidoctor::Reader.new "Stuart Rackham <founder@asciidoc.org>\n:Author Initials: SJR".lines.entries
|
361
|
+
metadata = Asciidoctor::Lexer.parse_header_metadata(reader, blankdoc)
|
362
|
+
assert_equal 'SR', metadata['authorinitials']
|
363
|
+
assert_equal 'SJR', blankdoc.attributes['authorinitials']
|
364
|
+
end
|
365
|
+
|
339
366
|
end
|
data/test/lists_test.rb
CHANGED
@@ -88,6 +88,22 @@ List
|
|
88
88
|
assert_xpath '(//ul)[2]/preceding-sibling::*[@class = "title"][text() = "Also"]', output, 1
|
89
89
|
end
|
90
90
|
|
91
|
+
test "dash elements separated by an attribute entry offset by a blank line should not merge lists" do
|
92
|
+
input = <<-EOS
|
93
|
+
== List
|
94
|
+
|
95
|
+
- Foo
|
96
|
+
- Boo
|
97
|
+
|
98
|
+
:foo: bar
|
99
|
+
- Blech
|
100
|
+
EOS
|
101
|
+
output = render_embedded_string input
|
102
|
+
assert_xpath '//ul', output, 2
|
103
|
+
assert_xpath '(//ul)[1]/li', output, 2
|
104
|
+
assert_xpath '(//ul)[2]/li', output, 1
|
105
|
+
end
|
106
|
+
|
91
107
|
test 'a non-indented wrapped line is folded into text of list item' do
|
92
108
|
input = <<-EOS
|
93
109
|
List
|
@@ -104,6 +120,36 @@ wrapped content
|
|
104
120
|
assert_xpath "//ul/li[1]/p[text() = 'Foo\nwrapped content']", output, 1
|
105
121
|
end
|
106
122
|
|
123
|
+
test 'a non-indented wrapped line that resembles a block title is folded into text of list item' do
|
124
|
+
input = <<-EOS
|
125
|
+
== List
|
126
|
+
|
127
|
+
- Foo
|
128
|
+
.wrapped content
|
129
|
+
- Boo
|
130
|
+
- Blech
|
131
|
+
EOS
|
132
|
+
output = render_embedded_string input
|
133
|
+
assert_xpath '//ul', output, 1
|
134
|
+
assert_xpath '//ul/li[1]/*', output, 1
|
135
|
+
assert_xpath "//ul/li[1]/p[text() = 'Foo\n.wrapped content']", output, 1
|
136
|
+
end
|
137
|
+
|
138
|
+
test 'a non-indented wrapped line that resembles an attribute entry is folded into text of list item' do
|
139
|
+
input = <<-EOS
|
140
|
+
== List
|
141
|
+
|
142
|
+
- Foo
|
143
|
+
:foo: bar
|
144
|
+
- Boo
|
145
|
+
- Blech
|
146
|
+
EOS
|
147
|
+
output = render_embedded_string input
|
148
|
+
assert_xpath '//ul', output, 1
|
149
|
+
assert_xpath '//ul/li[1]/*', output, 1
|
150
|
+
assert_xpath "//ul/li[1]/p[text() = 'Foo\n:foo: bar']", output, 1
|
151
|
+
end
|
152
|
+
|
107
153
|
test 'an indented wrapped line is unindented and folded into text of list item' do
|
108
154
|
input = <<-EOS
|
109
155
|
List
|
@@ -357,6 +403,22 @@ List
|
|
357
403
|
assert_xpath '(//ul)[2]/preceding-sibling::*[@class = "title"][text() = "Also"]', output, 1
|
358
404
|
end
|
359
405
|
|
406
|
+
test "asterisk elements separated by an attribute entry offset by a blank line should not merge lists" do
|
407
|
+
input = <<-EOS
|
408
|
+
== List
|
409
|
+
|
410
|
+
* Foo
|
411
|
+
* Boo
|
412
|
+
|
413
|
+
:foo: bar
|
414
|
+
* Blech
|
415
|
+
EOS
|
416
|
+
output = render_embedded_string input
|
417
|
+
assert_xpath '//ul', output, 2
|
418
|
+
assert_xpath '(//ul)[1]/li', output, 2
|
419
|
+
assert_xpath '(//ul)[2]/li', output, 1
|
420
|
+
end
|
421
|
+
|
360
422
|
test "list should terminate before next lower section heading" do
|
361
423
|
input = <<-EOS
|
362
424
|
List
|
@@ -815,6 +877,7 @@ Lists
|
|
815
877
|
|
816
878
|
* Item one, paragraph one
|
817
879
|
+
|
880
|
+
:foo: bar
|
818
881
|
[[beck]]
|
819
882
|
.Read the following aloud to yourself
|
820
883
|
[source, ruby]
|
@@ -1295,6 +1358,22 @@ List
|
|
1295
1358
|
assert_xpath '(//ol)[2]/li', output, 1
|
1296
1359
|
assert_xpath '(//ol)[2]/preceding-sibling::*[@class = "title"][text() = "Also"]', output, 1
|
1297
1360
|
end
|
1361
|
+
|
1362
|
+
test "dot elements separated by an attribute entry offset by a blank line should not merge lists" do
|
1363
|
+
input = <<-EOS
|
1364
|
+
== List
|
1365
|
+
|
1366
|
+
. Foo
|
1367
|
+
. Boo
|
1368
|
+
|
1369
|
+
:foo: bar
|
1370
|
+
. Blech
|
1371
|
+
EOS
|
1372
|
+
output = render_embedded_string input
|
1373
|
+
assert_xpath '//ol', output, 2
|
1374
|
+
assert_xpath '(//ol)[1]/li', output, 2
|
1375
|
+
assert_xpath '(//ol)[2]/li', output, 1
|
1376
|
+
end
|
1298
1377
|
end
|
1299
1378
|
end
|
1300
1379
|
|
data/test/paragraphs_test.rb
CHANGED
@@ -102,11 +102,19 @@ You're good to go!
|
|
102
102
|
assert_match(/^gem install asciidoctor/, output, "Indentation should be trimmed from literal block")
|
103
103
|
end
|
104
104
|
|
105
|
+
test "literal paragraph" do
|
106
|
+
assert_xpath "//*[@class='literalblock']//pre[text()='blah blah blah']", render_string("[literal]\nblah blah blah")
|
107
|
+
end
|
108
|
+
|
105
109
|
test "listing paragraph" do
|
106
|
-
assert_xpath "
|
110
|
+
assert_xpath "//*[@class='listingblock']//pre[text()='blah blah blah']", render_string("[listing]\nblah blah blah")
|
107
111
|
end
|
108
112
|
|
109
113
|
test "source code paragraph" do
|
114
|
+
assert_xpath "//pre[@class='highlight']/code", render_string("[source]\nblah blah blah")
|
115
|
+
end
|
116
|
+
|
117
|
+
test "source code paragraph with language" do
|
110
118
|
assert_xpath "//pre[@class='highlight']/code[@class='perl']", render_string("[source, perl]\ndie 'zomg perl sucks';")
|
111
119
|
end
|
112
120
|
end
|
data/test/reader_test.rb
CHANGED
@@ -7,13 +7,13 @@ class ReaderTest < Test::Unit::TestCase
|
|
7
7
|
@reader = Asciidoctor::Reader.new @src_data
|
8
8
|
end
|
9
9
|
|
10
|
-
context "
|
10
|
+
context "has_more_lines?" do
|
11
11
|
test "returns false for empty document" do
|
12
|
-
assert !Asciidoctor::Reader.new.
|
12
|
+
assert !Asciidoctor::Reader.new.has_more_lines?
|
13
13
|
end
|
14
14
|
|
15
15
|
test "returns true with lines remaining" do
|
16
|
-
assert @reader.
|
16
|
+
assert @reader.has_more_lines?, "Yo, didn't work"
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -57,7 +57,7 @@ This is another paragraph.
|
|
57
57
|
result = reader.grab_lines_until
|
58
58
|
assert_equal 3, result.size
|
59
59
|
assert_equal lines, result
|
60
|
-
assert !reader.
|
60
|
+
assert !reader.has_more_lines?
|
61
61
|
assert reader.empty?
|
62
62
|
end
|
63
63
|
|
@@ -181,10 +181,14 @@ include::include-file.asciidoc[]
|
|
181
181
|
last line
|
182
182
|
EOS
|
183
183
|
doc = Asciidoctor::Document.new [], :safe => Asciidoctor::SafeMode::SAFE
|
184
|
-
Asciidoctor::Reader.new(input.lines.entries, doc) {|inc|
|
185
|
-
":
|
184
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true) {|inc|
|
185
|
+
":includefile: #{inc}\n\nmiddle line".lines.entries
|
186
186
|
}
|
187
|
-
|
187
|
+
lines = []
|
188
|
+
while reader.has_more_lines?
|
189
|
+
lines << reader.get_line
|
190
|
+
end
|
191
|
+
assert_match(/^:includefile: include-file.asciidoc$/, lines.join)
|
188
192
|
end
|
189
193
|
|
190
194
|
test 'escaped include macro is left unprocessed' do
|
@@ -231,7 +235,7 @@ include::include-file.asciidoc[]
|
|
231
235
|
context 'build secure asset path' do
|
232
236
|
test 'allows us to specify a path relative to the current dir' do
|
233
237
|
doc = Asciidoctor::Document.new
|
234
|
-
Asciidoctor::Reader.new([
|
238
|
+
Asciidoctor::Reader.new([], doc, true)
|
235
239
|
legit_path = Dir.pwd + "/foo"
|
236
240
|
assert_equal legit_path, doc.normalize_asset_path(legit_path)
|
237
241
|
end
|
@@ -239,7 +243,7 @@ include::include-file.asciidoc[]
|
|
239
243
|
test "keeps naughty absolute paths from getting outside" do
|
240
244
|
naughty_path = "#{disk_root}etc/passwd"
|
241
245
|
doc = Asciidoctor::Document.new
|
242
|
-
Asciidoctor::Reader.new([
|
246
|
+
Asciidoctor::Reader.new([], doc, true)
|
243
247
|
secure_path = doc.normalize_asset_path(naughty_path)
|
244
248
|
assert naughty_path != secure_path
|
245
249
|
assert_match(/^#{doc.base_dir}/, secure_path)
|
@@ -248,26 +252,247 @@ include::include-file.asciidoc[]
|
|
248
252
|
test "keeps naughty relative paths from getting outside" do
|
249
253
|
naughty_path = "safe/ok/../../../../../etc/passwd"
|
250
254
|
doc = Asciidoctor::Document.new
|
251
|
-
Asciidoctor::Reader.new([
|
255
|
+
Asciidoctor::Reader.new([], doc, true)
|
252
256
|
secure_path = doc.normalize_asset_path(naughty_path)
|
253
257
|
assert naughty_path != secure_path
|
254
258
|
assert_match(/^#{doc.base_dir}/, secure_path)
|
255
259
|
end
|
256
260
|
end
|
257
261
|
|
258
|
-
|
259
|
-
|
260
|
-
|
262
|
+
context 'Conditional Inclusions' do
|
263
|
+
test 'preprocess_next_line returns true if cursor advanced' do
|
264
|
+
input = <<-EOS
|
265
|
+
ifdef::asciidoctor[]
|
266
|
+
Asciidoctor!
|
267
|
+
endif::asciidoctor[]
|
268
|
+
EOS
|
269
|
+
|
270
|
+
doc = Asciidoctor::Document.new
|
271
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
272
|
+
assert reader.preprocess_next_line == true
|
273
|
+
end
|
274
|
+
|
275
|
+
test 'preprocess_next_line returns false if cursor not advanced' do
|
276
|
+
input = <<-EOS
|
277
|
+
content
|
278
|
+
ifdef::asciidoctor[]
|
279
|
+
Asciidoctor!
|
280
|
+
endif::asciidoctor[]
|
281
|
+
EOS
|
282
|
+
|
283
|
+
doc = Asciidoctor::Document.new
|
284
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
285
|
+
assert reader.preprocess_next_line == false
|
286
|
+
end
|
287
|
+
|
288
|
+
test 'preprocess_next_line returns nil if cursor advanced past end of source' do
|
261
289
|
input = <<-EOS
|
262
|
-
|
290
|
+
ifdef::foobar[]
|
291
|
+
swallowed content
|
292
|
+
endif::foobar[]
|
293
|
+
EOS
|
263
294
|
|
295
|
+
doc = Asciidoctor::Document.new
|
296
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
297
|
+
assert reader.preprocess_next_line.nil?
|
298
|
+
end
|
299
|
+
|
300
|
+
test 'ifdef with defined attribute includes block' do
|
301
|
+
input = <<-EOS
|
264
302
|
ifdef::holygrail[]
|
265
303
|
There is a holy grail!
|
266
304
|
endif::holygrail[]
|
267
305
|
EOS
|
268
306
|
|
269
|
-
|
270
|
-
|
307
|
+
doc = Asciidoctor::Document.new [], :attributes => {'holygrail' => ''}
|
308
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
309
|
+
lines = []
|
310
|
+
while reader.has_more_lines?
|
311
|
+
lines << reader.get_line
|
312
|
+
end
|
313
|
+
assert_equal 'There is a holy grail!', lines.join.strip
|
314
|
+
end
|
315
|
+
|
316
|
+
test 'ifdef with defined attribute includes text in brackets' do
|
317
|
+
input = <<-EOS
|
318
|
+
On our quest we go...
|
319
|
+
ifdef::holygrail[There is a holy grail!]
|
320
|
+
There was much rejoicing.
|
321
|
+
EOS
|
322
|
+
|
323
|
+
doc = Asciidoctor::Document.new [], :attributes => {'holygrail' => ''}
|
324
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
325
|
+
lines = []
|
326
|
+
while reader.has_more_lines?
|
327
|
+
lines << reader.get_line
|
328
|
+
end
|
329
|
+
assert_equal "On our quest we go...\nThere is a holy grail!\nThere was much rejoicing.", lines.join.strip
|
330
|
+
end
|
331
|
+
|
332
|
+
test 'include with non-matching nested exclude' do
|
333
|
+
input = <<-EOS
|
334
|
+
ifdef::grail[]
|
335
|
+
holy
|
336
|
+
ifdef::swallow[]
|
337
|
+
swallow
|
338
|
+
endif::swallow[]
|
339
|
+
grail
|
340
|
+
endif::grail[]
|
341
|
+
EOS
|
342
|
+
|
343
|
+
doc = Asciidoctor::Document.new [], :attributes => {'grail' => ''}
|
344
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
345
|
+
lines = []
|
346
|
+
while reader.has_more_lines?
|
347
|
+
lines << reader.get_line
|
348
|
+
end
|
349
|
+
assert_equal "holy\ngrail", lines.join.strip
|
350
|
+
end
|
351
|
+
|
352
|
+
test 'nested excludes with same condition' do
|
353
|
+
input = <<-EOS
|
354
|
+
ifndef::grail[]
|
355
|
+
ifndef::grail[]
|
356
|
+
not here
|
357
|
+
endif::grail[]
|
358
|
+
endif::grail[]
|
359
|
+
EOS
|
360
|
+
|
361
|
+
doc = Asciidoctor::Document.new [], :attributes => {'grail' => ''}
|
362
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
363
|
+
lines = []
|
364
|
+
while reader.has_more_lines?
|
365
|
+
lines << reader.get_line
|
366
|
+
end
|
367
|
+
assert_equal '', lines.join.strip
|
368
|
+
end
|
369
|
+
|
370
|
+
test 'include with nested exclude of inverted condition' do
|
371
|
+
input = <<-EOS
|
372
|
+
ifdef::grail[]
|
373
|
+
holy
|
374
|
+
ifndef::grail[]
|
375
|
+
not here
|
376
|
+
endif::grail[]
|
377
|
+
grail
|
378
|
+
endif::grail[]
|
379
|
+
EOS
|
380
|
+
|
381
|
+
doc = Asciidoctor::Document.new [], :attributes => {'grail' => ''}
|
382
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
383
|
+
lines = []
|
384
|
+
while reader.has_more_lines?
|
385
|
+
lines << reader.get_line
|
386
|
+
end
|
387
|
+
assert_equal "holy\ngrail", lines.join.strip
|
388
|
+
end
|
389
|
+
|
390
|
+
test 'exclude with matching nested exclude' do
|
391
|
+
input = <<-EOS
|
392
|
+
poof
|
393
|
+
ifdef::swallow[]
|
394
|
+
no
|
395
|
+
ifdef::swallow[]
|
396
|
+
swallow
|
397
|
+
endif::swallow[]
|
398
|
+
here
|
399
|
+
endif::swallow[]
|
400
|
+
gone
|
401
|
+
EOS
|
402
|
+
|
403
|
+
doc = Asciidoctor::Document.new [], :attributes => {'grail' => ''}
|
404
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
405
|
+
lines = []
|
406
|
+
while reader.has_more_lines?
|
407
|
+
lines << reader.get_line
|
408
|
+
end
|
409
|
+
assert_equal "poof\ngone", lines.join.strip
|
410
|
+
end
|
411
|
+
|
412
|
+
test 'exclude with nested include using shorthand end' do
|
413
|
+
input = <<-EOS
|
414
|
+
poof
|
415
|
+
ifndef::grail[]
|
416
|
+
no grail
|
417
|
+
ifndef::swallow[]
|
418
|
+
or swallow
|
419
|
+
endif::[]
|
420
|
+
in here
|
421
|
+
endif::[]
|
422
|
+
gone
|
423
|
+
EOS
|
424
|
+
|
425
|
+
doc = Asciidoctor::Document.new [], :attributes => {'grail' => ''}
|
426
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
427
|
+
lines = []
|
428
|
+
while reader.has_more_lines?
|
429
|
+
lines << reader.get_line
|
430
|
+
end
|
431
|
+
assert_equal "poof\ngone", lines.join.strip
|
432
|
+
end
|
433
|
+
|
434
|
+
test 'ifdef with one alternative attribute set includes content' do
|
435
|
+
input = <<-EOS
|
436
|
+
ifdef::holygrail,swallow[]
|
437
|
+
Our quest is complete!
|
438
|
+
endif::holygrail,swallow[]
|
439
|
+
EOS
|
440
|
+
|
441
|
+
doc = Asciidoctor::Document.new [], :attributes => {'swallow' => ''}
|
442
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
443
|
+
lines = []
|
444
|
+
while reader.has_more_lines?
|
445
|
+
lines << reader.get_line
|
446
|
+
end
|
447
|
+
assert_equal 'Our quest is complete!', lines.join.strip
|
448
|
+
end
|
449
|
+
|
450
|
+
test 'ifdef with no alternative attributes set does not include content' do
|
451
|
+
input = <<-EOS
|
452
|
+
ifdef::holygrail,swallow[]
|
453
|
+
Our quest is complete!
|
454
|
+
endif::holygrail,swallow[]
|
455
|
+
EOS
|
456
|
+
|
457
|
+
doc = Asciidoctor::Document.new
|
458
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
459
|
+
lines = []
|
460
|
+
while reader.has_more_lines?
|
461
|
+
lines << reader.get_line
|
462
|
+
end
|
463
|
+
assert_equal '', lines.join.strip
|
464
|
+
end
|
465
|
+
|
466
|
+
test 'ifdef with all required attributes set includes content' do
|
467
|
+
input = <<-EOS
|
468
|
+
ifdef::holygrail+swallow[]
|
469
|
+
Our quest is complete!
|
470
|
+
endif::holygrail+swallow[]
|
471
|
+
EOS
|
472
|
+
|
473
|
+
doc = Asciidoctor::Document.new [], :attributes => {'holygrail' => '', 'swallow' => ''}
|
474
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
475
|
+
lines = []
|
476
|
+
while reader.has_more_lines?
|
477
|
+
lines << reader.get_line
|
478
|
+
end
|
479
|
+
assert_equal 'Our quest is complete!', lines.join.strip
|
480
|
+
end
|
481
|
+
|
482
|
+
test 'ifdef with missing required attributes does not include content' do
|
483
|
+
input = <<-EOS
|
484
|
+
ifdef::holygrail+swallow[]
|
485
|
+
Our quest is complete!
|
486
|
+
endif::holygrail+swallow[]
|
487
|
+
EOS
|
488
|
+
|
489
|
+
doc = Asciidoctor::Document.new [], :attributes => {'holygrail' => ''}
|
490
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
491
|
+
lines = []
|
492
|
+
while reader.has_more_lines?
|
493
|
+
lines << reader.get_line
|
494
|
+
end
|
495
|
+
assert_equal '', lines.join.strip
|
271
496
|
end
|
272
497
|
|
273
498
|
test 'ifndef with undefined attribute includes block' do
|
@@ -277,8 +502,220 @@ Our quest continues to find the holy grail!
|
|
277
502
|
endif::holygrail[]
|
278
503
|
EOS
|
279
504
|
|
280
|
-
|
281
|
-
|
505
|
+
doc = Asciidoctor::Document.new
|
506
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
507
|
+
lines = []
|
508
|
+
while reader.has_more_lines?
|
509
|
+
lines << reader.get_line
|
510
|
+
end
|
511
|
+
assert_equal 'Our quest continues to find the holy grail!', lines.join.strip
|
512
|
+
end
|
513
|
+
|
514
|
+
test 'ifndef with one alternative attribute set includes content' do
|
515
|
+
input = <<-EOS
|
516
|
+
ifndef::holygrail,swallow[]
|
517
|
+
Our quest is complete!
|
518
|
+
endif::holygrail,swallow[]
|
519
|
+
EOS
|
520
|
+
|
521
|
+
doc = Asciidoctor::Document.new [], :attributes => {'swallow' => ''}
|
522
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
523
|
+
lines = []
|
524
|
+
while reader.has_more_lines?
|
525
|
+
lines << reader.get_line
|
526
|
+
end
|
527
|
+
assert_equal 'Our quest is complete!', lines.join.strip
|
528
|
+
end
|
529
|
+
|
530
|
+
test 'ifndef with no alternative attributes set includes content' do
|
531
|
+
input = <<-EOS
|
532
|
+
ifndef::holygrail,swallow[]
|
533
|
+
Our quest is complete!
|
534
|
+
endif::holygrail,swallow[]
|
535
|
+
EOS
|
536
|
+
|
537
|
+
doc = Asciidoctor::Document.new
|
538
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
539
|
+
lines = []
|
540
|
+
while reader.has_more_lines?
|
541
|
+
lines << reader.get_line
|
542
|
+
end
|
543
|
+
assert_equal 'Our quest is complete!', lines.join.strip
|
544
|
+
end
|
545
|
+
|
546
|
+
test 'ifndef with any required attributes set does not include content' do
|
547
|
+
input = <<-EOS
|
548
|
+
ifndef::holygrail+swallow[]
|
549
|
+
Our quest is complete!
|
550
|
+
endif::holygrail+swallow[]
|
551
|
+
EOS
|
552
|
+
|
553
|
+
doc = Asciidoctor::Document.new [], :attributes => {'swallow' => ''}
|
554
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
555
|
+
lines = []
|
556
|
+
while reader.has_more_lines?
|
557
|
+
lines << reader.get_line
|
558
|
+
end
|
559
|
+
assert_equal '', lines.join.strip
|
560
|
+
end
|
561
|
+
|
562
|
+
test 'ifndef with no required attributes set includes content' do
|
563
|
+
input = <<-EOS
|
564
|
+
ifndef::holygrail+swallow[]
|
565
|
+
Our quest is complete!
|
566
|
+
endif::holygrail+swallow[]
|
567
|
+
EOS
|
568
|
+
|
569
|
+
doc = Asciidoctor::Document.new
|
570
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
571
|
+
lines = []
|
572
|
+
while reader.has_more_lines?
|
573
|
+
lines << reader.get_line
|
574
|
+
end
|
575
|
+
assert_equal 'Our quest is complete!', lines.join.strip
|
576
|
+
end
|
577
|
+
|
578
|
+
test 'escaped ifdef is unescaped and ignored' do
|
579
|
+
input = <<-EOS
|
580
|
+
\\ifdef::holygrail[]
|
581
|
+
content
|
582
|
+
\\endif::holygrail[]
|
583
|
+
EOS
|
584
|
+
|
585
|
+
doc = Asciidoctor::Document.new
|
586
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
587
|
+
lines = []
|
588
|
+
while reader.has_more_lines?
|
589
|
+
lines << reader.get_line
|
590
|
+
end
|
591
|
+
assert_equal "ifdef::holygrail[]\ncontent\nendif::holygrail[]", lines.join.strip
|
592
|
+
end
|
593
|
+
|
594
|
+
test 'ifeval comparing double-quoted attribute to matching string is included' do
|
595
|
+
input = <<-EOS
|
596
|
+
ifeval::["{gem}" == "asciidoctor"]
|
597
|
+
Asciidoctor it is!
|
598
|
+
endif::[]
|
599
|
+
EOS
|
600
|
+
|
601
|
+
doc = Asciidoctor::Document.new [], :attributes => {'gem' => 'asciidoctor'}
|
602
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
603
|
+
lines = []
|
604
|
+
while reader.has_more_lines?
|
605
|
+
lines << reader.get_line
|
606
|
+
end
|
607
|
+
assert_equal 'Asciidoctor it is!', lines.join.strip
|
608
|
+
end
|
609
|
+
|
610
|
+
test 'ifeval comparing single-quoted attribute to matching string is included' do
|
611
|
+
input = <<-EOS
|
612
|
+
ifeval::['{gem}' == 'asciidoctor']
|
613
|
+
Asciidoctor it is!
|
614
|
+
endif::[]
|
615
|
+
EOS
|
616
|
+
|
617
|
+
doc = Asciidoctor::Document.new [], :attributes => {'gem' => 'asciidoctor'}
|
618
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
619
|
+
lines = []
|
620
|
+
while reader.has_more_lines?
|
621
|
+
lines << reader.get_line
|
622
|
+
end
|
623
|
+
assert_equal 'Asciidoctor it is!', lines.join.strip
|
624
|
+
end
|
625
|
+
|
626
|
+
test 'ifeval comparing quoted attribute to non-matching string is ignored' do
|
627
|
+
input = <<-EOS
|
628
|
+
ifeval::['{gem}' == 'asciidoctor']
|
629
|
+
Asciidoctor it is!
|
630
|
+
endif::[]
|
631
|
+
EOS
|
632
|
+
|
633
|
+
doc = Asciidoctor::Document.new [], :attributes => {'gem' => 'tilt'}
|
634
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
635
|
+
lines = []
|
636
|
+
while reader.has_more_lines?
|
637
|
+
lines << reader.get_line
|
638
|
+
end
|
639
|
+
assert_equal '', lines.join.strip
|
640
|
+
end
|
641
|
+
|
642
|
+
test 'ifeval comparing attribute to lower version number is included' do
|
643
|
+
input = <<-EOS
|
644
|
+
ifeval::['{asciidoctor-version}' >= '0.1.0']
|
645
|
+
That version will do!
|
646
|
+
endif::[]
|
647
|
+
EOS
|
648
|
+
|
649
|
+
doc = Asciidoctor::Document.new
|
650
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
651
|
+
lines = []
|
652
|
+
while reader.has_more_lines?
|
653
|
+
lines << reader.get_line
|
654
|
+
end
|
655
|
+
assert_equal 'That version will do!', lines.join.strip
|
656
|
+
end
|
657
|
+
|
658
|
+
test 'ifeval comparing attribute to self is included' do
|
659
|
+
input = <<-EOS
|
660
|
+
ifeval::['{asciidoctor-version}' == '{asciidoctor-version}']
|
661
|
+
Of course it's the same!
|
662
|
+
endif::[]
|
663
|
+
EOS
|
664
|
+
|
665
|
+
doc = Asciidoctor::Document.new
|
666
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
667
|
+
lines = []
|
668
|
+
while reader.has_more_lines?
|
669
|
+
lines << reader.get_line
|
670
|
+
end
|
671
|
+
assert_equal 'Of course it\'s the same!', lines.join.strip
|
672
|
+
end
|
673
|
+
|
674
|
+
test 'ifeval arguments can be mirrored' do
|
675
|
+
input = <<-EOS
|
676
|
+
ifeval::["0.1.0" <= "{asciidoctor-version}"]
|
677
|
+
That version will do!
|
678
|
+
endif::[]
|
679
|
+
EOS
|
680
|
+
|
681
|
+
doc = Asciidoctor::Document.new
|
682
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
683
|
+
lines = []
|
684
|
+
while reader.has_more_lines?
|
685
|
+
lines << reader.get_line
|
686
|
+
end
|
687
|
+
assert_equal 'That version will do!', lines.join.strip
|
688
|
+
end
|
689
|
+
|
690
|
+
test 'ifeval matching numeric comparison is included' do
|
691
|
+
input = <<-EOS
|
692
|
+
ifeval::[{rings} == 1]
|
693
|
+
One ring to rule them all!
|
694
|
+
endif::[]
|
695
|
+
EOS
|
696
|
+
|
697
|
+
doc = Asciidoctor::Document.new [], :attributes => {'rings' => 1}
|
698
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
699
|
+
lines = []
|
700
|
+
while reader.has_more_lines?
|
701
|
+
lines << reader.get_line
|
702
|
+
end
|
703
|
+
assert_equal 'One ring to rule them all!', lines.join.strip
|
704
|
+
end
|
705
|
+
|
706
|
+
test 'ifdef with no target is ignored' do
|
707
|
+
input = <<-EOS
|
708
|
+
ifdef::[]
|
709
|
+
content
|
710
|
+
EOS
|
711
|
+
|
712
|
+
doc = Asciidoctor::Document.new
|
713
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, doc, true)
|
714
|
+
lines = []
|
715
|
+
while reader.has_more_lines?
|
716
|
+
lines << reader.get_line
|
717
|
+
end
|
718
|
+
assert_equal "ifdef::[]\ncontent", lines.join.strip
|
282
719
|
end
|
283
720
|
end
|
284
721
|
|
@@ -291,7 +728,7 @@ CRLF\r
|
|
291
728
|
endlines\r
|
292
729
|
EOS
|
293
730
|
|
294
|
-
reader = Asciidoctor::Reader.new(input.lines.entries, Asciidoctor::Document.new)
|
731
|
+
reader = Asciidoctor::Reader.new(input.lines.entries, Asciidoctor::Document.new, true)
|
295
732
|
reader.lines.each do |line|
|
296
733
|
assert !line.end_with?("\r\n")
|
297
734
|
end
|