asciidoctor 0.1.1 → 0.1.2

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.

Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +1 -1
  3. data/LICENSE +2 -2
  4. data/README.adoc +461 -0
  5. data/asciidoctor.gemspec +27 -16
  6. data/compat/asciidoc.conf +139 -0
  7. data/lib/asciidoctor.rb +212 -69
  8. data/lib/asciidoctor/abstract_block.rb +41 -0
  9. data/lib/asciidoctor/abstract_node.rb +128 -81
  10. data/lib/asciidoctor/attribute_list.rb +5 -2
  11. data/lib/asciidoctor/backends/base_template.rb +16 -4
  12. data/lib/asciidoctor/backends/docbook45.rb +112 -42
  13. data/lib/asciidoctor/backends/html5.rb +206 -90
  14. data/lib/asciidoctor/block.rb +5 -5
  15. data/lib/asciidoctor/cli/invoker.rb +38 -34
  16. data/lib/asciidoctor/cli/options.rb +3 -3
  17. data/lib/asciidoctor/document.rb +115 -13
  18. data/lib/asciidoctor/helpers.rb +16 -0
  19. data/lib/asciidoctor/lexer.rb +486 -359
  20. data/lib/asciidoctor/path_resolver.rb +360 -0
  21. data/lib/asciidoctor/reader.rb +122 -23
  22. data/lib/asciidoctor/renderer.rb +1 -33
  23. data/lib/asciidoctor/section.rb +1 -1
  24. data/lib/asciidoctor/substituters.rb +103 -19
  25. data/lib/asciidoctor/version.rb +1 -1
  26. data/man/asciidoctor.1 +6 -6
  27. data/man/asciidoctor.ad +5 -3
  28. data/stylesheets/asciidoctor.css +274 -0
  29. data/test/attributes_test.rb +133 -10
  30. data/test/blocks_test.rb +302 -17
  31. data/test/document_test.rb +269 -6
  32. data/test/fixtures/basic-docinfo.html +1 -0
  33. data/test/fixtures/basic-docinfo.xml +4 -0
  34. data/test/fixtures/basic.asciidoc +4 -0
  35. data/test/fixtures/docinfo.html +1 -0
  36. data/test/fixtures/docinfo.xml +2 -0
  37. data/test/fixtures/include-file.asciidoc +22 -1
  38. data/test/fixtures/stylesheets/custom.css +3 -0
  39. data/test/invoker_test.rb +38 -6
  40. data/test/lexer_test.rb +64 -21
  41. data/test/links_test.rb +4 -0
  42. data/test/lists_test.rb +251 -12
  43. data/test/paragraphs_test.rb +225 -30
  44. data/test/paths_test.rb +174 -0
  45. data/test/reader_test.rb +89 -2
  46. data/test/sections_test.rb +518 -16
  47. data/test/substitutions_test.rb +121 -10
  48. data/test/tables_test.rb +53 -13
  49. data/test/test_helper.rb +2 -2
  50. data/test/text_test.rb +5 -5
  51. metadata +46 -50
  52. data/README.asciidoc +0 -296
  53. data/lib/asciidoctor/errors.rb +0 -5
@@ -1,21 +1,53 @@
1
1
  require 'test_helper'
2
2
 
3
- context "Paragraphs" do
3
+ context 'Paragraphs' do
4
4
  context 'Normal' do
5
- test "rendered correctly" do
6
- assert_xpath "//p", render_string("Plain text for the win.\n\nYes, plainly."), 2
5
+ test 'should treat plain text separated by blank lines as paragraphs' do
6
+ input = <<-EOS
7
+ Plain text for the win!
8
+
9
+ Yep. Text. Plain and simple.
10
+ EOS
11
+ output = render_embedded_string input
12
+ assert_css 'p', output, 2
13
+ assert_xpath '(//p)[1][text() = "Plain text for the win!"]', output, 1
14
+ assert_xpath '(//p)[2][text() = "Yep. Text. Plain and simple."]', output, 1
7
15
  end
8
16
 
9
- test "with title" do
10
- rendered = render_string(".Titled\nParagraph.\n\nWinning")
17
+ test 'should associate block title with paragraph' do
18
+ input = <<-EOS
19
+ .Titled
20
+ Paragraph.
21
+
22
+ Winning.
23
+ EOS
24
+ output = render_embedded_string input
11
25
 
12
- assert_xpath "//div[@class='title']", rendered
13
- assert_xpath "//p", rendered, 2
26
+ assert_css 'p', output, 2
27
+ assert_xpath '(//p)[1]/preceding-sibling::*[@class = "title"]', output, 1
28
+ assert_xpath '(//p)[1]/preceding-sibling::*[@class = "title"][text() = "Titled"]', output, 1
29
+ assert_xpath '(//p)[2]/preceding-sibling::*[@class = "title"]', output, 0
14
30
  end
15
31
 
16
- test "no duplicate block before next section" do
17
- rendered = render_string("Title\n=====\n\nPreamble.\n\n== First Section\n\nParagraph 1\n\nParagraph 2\n\n\n== Second Section\n\nLast words")
18
- assert_xpath '//p[text()="Paragraph 2"]', rendered, 1
32
+ test 'no duplicate block before next section' do
33
+ input = <<-EOS
34
+ = Title
35
+
36
+ Preamble
37
+
38
+ == First Section
39
+
40
+ Paragraph 1
41
+
42
+ Paragraph 2
43
+
44
+ == Second Section
45
+
46
+ Last words
47
+ EOS
48
+
49
+ output = render_string input
50
+ assert_xpath '//p[text() = "Paragraph 2"]', output, 1
19
51
  end
20
52
 
21
53
  test 'does not treat wrapped line as a list item' do
@@ -40,6 +72,62 @@ paragraph
40
72
  assert_xpath %(//p[text()="paragraph\n.wrapped line"]), output, 1
41
73
  end
42
74
 
75
+ test 'interprets normal paragraph style as normal paragraph' do
76
+ input = <<-EOS
77
+ [normal]
78
+ Normal paragraph.
79
+ Nothing special.
80
+ EOS
81
+
82
+ output = render_embedded_string input
83
+ assert_css 'p', output, 1
84
+ end
85
+
86
+ test 'normal paragraph terminates at block attribute list' do
87
+ input = <<-EOS
88
+ normal text
89
+ [literal]
90
+ literal text
91
+ EOS
92
+ output = render_embedded_string input
93
+ assert_css '.paragraph:root', output, 1
94
+ assert_css '.literalblock:root', output, 1
95
+ end
96
+
97
+ test 'normal paragraph terminates at block delimiter' do
98
+ input = <<-EOS
99
+ normal text
100
+ --
101
+ text in open block
102
+ --
103
+ EOS
104
+ output = render_embedded_string input
105
+ assert_css '.paragraph:root', output, 1
106
+ assert_css '.openblock:root', output, 1
107
+ end
108
+
109
+ test 'normal paragraph terminates at list continuation' do
110
+ input = <<-EOS
111
+ normal text
112
+ +
113
+ EOS
114
+ output = render_embedded_string input
115
+ assert_css '.paragraph:root', output, 2
116
+ assert_xpath %((/*[@class="paragraph"])[1]/p[text() = "normal text"]), output, 1
117
+ assert_xpath %((/*[@class="paragraph"])[2]/p[text() = "+"]), output, 1
118
+ end
119
+
120
+ test 'normal style turns literal paragraph into normal paragraph' do
121
+ input = <<-EOS
122
+ [normal]
123
+ normal paragraph,
124
+ despite the leading indent
125
+ EOS
126
+
127
+ output = render_embedded_string input
128
+ assert_css '.paragraph:root > p', output, 1
129
+ end
130
+
43
131
  test 'expands index term macros in DocBook backend' do
44
132
  input = <<-EOS
45
133
  Here is an index entry for ((tigers)).
@@ -81,14 +169,32 @@ Note that multi-entry terms generate separate index entries.
81
169
  assert_xpath '(//indexterm)[7]/*', output, 2
82
170
  assert_xpath '(//indexterm)[8]/*', output, 1
83
171
  end
172
+
173
+ test 'normal paragraph should honor explicit subs list' do
174
+ input = <<-EOS
175
+ [subs="specialcharacters"]
176
+ *Hey Jude*
177
+ EOS
178
+
179
+ output = render_embedded_string input
180
+ assert output.include?('*Hey Jude*')
181
+ end
84
182
  end
85
183
 
86
- context "code" do
87
- test "single-line literal paragraphs" do
88
- assert_xpath "//pre", render_string(" LITERALS\n\n ARE LITERALLY\n\n AWESOMMMME.")
184
+ context 'Literal' do
185
+ test 'single-line literal paragraphs' do
186
+ input = <<-EOS
187
+ LITERALS
188
+
189
+ ARE LITERALLY
190
+
191
+ AWESOME!
192
+ EOS
193
+ output = render_embedded_string input
194
+ assert_xpath '//pre', output, 3
89
195
  end
90
196
 
91
- test "multi-line literal paragraph" do
197
+ test 'multi-line literal paragraph' do
92
198
  input = <<-EOS
93
199
  Install instructions:
94
200
 
@@ -97,29 +203,95 @@ Install instructions:
97
203
 
98
204
  You're good to go!
99
205
  EOS
100
- output = render_string(input)
101
- assert_xpath "//pre", output, 1
102
- assert_match(/^gem install asciidoctor/, output, "Indentation should be trimmed from literal block")
206
+ output = render_embedded_string input
207
+ assert_xpath '//pre', output, 1
208
+ # indentation should be trimmed from literal block
209
+ assert_xpath %(//pre[text() = "yum install ruby rubygems\ngem install asciidoctor"]), output, 1
210
+ end
211
+
212
+ test 'literal paragraph' do
213
+ input = <<-EOS
214
+ [literal]
215
+ this text is literally literal
216
+ EOS
217
+ output = render_embedded_string input
218
+ assert_xpath %(/*[@class="literalblock"]//pre[text()="this text is literally literal"]), output, 1
219
+ end
220
+
221
+ test 'should read content below literal style verbatim' do
222
+ input = <<-EOS
223
+ [literal]
224
+ image::not-an-image-block[]
225
+ EOS
226
+ output = render_embedded_string input
227
+ assert_xpath %(/*[@class="literalblock"]//pre[text()="image::not-an-image-block[]"]), output, 1
228
+ assert_css 'img', output, 0
229
+ end
230
+
231
+ test 'listing paragraph' do
232
+ input = <<-EOS
233
+ [listing]
234
+ this text is a listing
235
+ EOS
236
+ output = render_embedded_string input
237
+ assert_xpath %(/*[@class="listingblock"]//pre[text()="this text is a listing"]), output, 1
238
+ end
239
+
240
+ test 'source paragraph' do
241
+ input = <<-EOS
242
+ [source]
243
+ use the source, luke!
244
+ EOS
245
+ output = render_embedded_string input
246
+ assert_xpath %(/*[@class="listingblock"]//pre[@class="highlight"]/code[text()="use the source, luke!"]), output, 1
103
247
  end
104
248
 
105
- test "literal paragraph" do
106
- assert_xpath "//*[@class='literalblock']//pre[text()='blah blah blah']", render_string("[literal]\nblah blah blah")
249
+ test 'source code paragraph with language' do
250
+ input = <<-EOS
251
+ [source, perl]
252
+ die 'zomg perl sucks';
253
+ EOS
254
+ output = render_embedded_string input
255
+ assert_xpath %(/*[@class="listingblock"]//pre[@class="highlight"]/code[@class="perl"][text()="die 'zomg perl sucks';"]), output, 1
107
256
  end
108
257
 
109
- test "listing paragraph" do
110
- assert_xpath "//*[@class='listingblock']//pre[text()='blah blah blah']", render_string("[listing]\nblah blah blah")
258
+ test 'literal paragraph terminates at block attribute list' do
259
+ input = <<-EOS
260
+ literal text
261
+ [normal]
262
+ normal text
263
+ EOS
264
+ output = render_embedded_string input
265
+ assert_xpath %(/*[@class="literalblock"]), output, 1
266
+ assert_xpath %(/*[@class="paragraph"]), output, 1
111
267
  end
112
268
 
113
- test "source code paragraph" do
114
- assert_xpath "//pre[@class='highlight']/code", render_string("[source]\nblah blah blah")
269
+ test 'literal paragraph terminates at block delimiter' do
270
+ input = <<-EOS
271
+ literal text
272
+ --
273
+ normal text
274
+ --
275
+ EOS
276
+ output = render_embedded_string input
277
+ assert_xpath %(/*[@class="literalblock"]), output, 1
278
+ assert_xpath %(/*[@class="openblock"]), output, 1
115
279
  end
116
280
 
117
- test "source code paragraph with language" do
118
- assert_xpath "//pre[@class='highlight']/code[@class='perl']", render_string("[source, perl]\ndie 'zomg perl sucks';")
281
+ test 'literal paragraph terminates at list continuation' do
282
+ input = <<-EOS
283
+ literal text
284
+ +
285
+ EOS
286
+ output = render_embedded_string input
287
+ assert_xpath %(/*[@class="literalblock"]), output, 1
288
+ assert_xpath %(/*[@class="literalblock"]//pre[text() = "literal text"]), output, 1
289
+ assert_xpath %(/*[@class="paragraph"]), output, 1
290
+ assert_xpath %(/*[@class="paragraph"]/p[text() = "+"]), output, 1
119
291
  end
120
292
  end
121
293
 
122
- context "quote" do
294
+ context 'Quote' do
123
295
  test "quote block" do
124
296
  output = render_string("____\nFamous quote.\n____")
125
297
  assert_xpath '//*[@class = "quoteblock"]', output, 1
@@ -137,7 +309,7 @@ You're good to go!
137
309
  test "quote block with section body" do
138
310
  output = render_string("____\nFamous quote.\n\nNOTE: That was inspiring.\n____")
139
311
  assert_xpath '//*[@class = "quoteblock"]', output, 1
140
- assert_xpath '//*[@class = "quoteblock"]//*[@class = "admonitionblock"]', output, 1
312
+ assert_xpath '//*[@class = "quoteblock"]//*[@class = "admonitionblock note"]', output, 1
141
313
  end
142
314
 
143
315
  test "single-line quote paragraph" do
@@ -147,6 +319,18 @@ You're good to go!
147
319
  assert_xpath '//*[@class = "quoteblock"]//*[contains(text(), "Famous quote.")]', output, 1
148
320
  end
149
321
 
322
+ test 'quote paragraph terminates at list continuation' do
323
+ input = <<-EOS
324
+ [quote]
325
+ A famouse quote.
326
+ +
327
+ EOS
328
+ output = render_embedded_string input
329
+ assert_css '.quoteblock:root', output, 1
330
+ assert_css '.paragraph:root', output, 1
331
+ assert_xpath %(/*[@class="paragraph"]/p[text() = "+"]), output, 1
332
+ end
333
+
150
334
  test "verse paragraph" do
151
335
  output = render_string("[verse]\nFamous verse.")
152
336
  assert_xpath '//*[@class = "verseblock"]', output, 1
@@ -179,24 +363,35 @@ You're good to go!
179
363
  assert_xpath '//*[@class = "verseblock"]//p', output, 0
180
364
  assert_xpath '//*[@class = "verseblock"]//*[@class = "literalblock"]', output, 0
181
365
  end
366
+
367
+ test 'quote paragraph should honor explicit subs list' do
368
+ input = <<-EOS
369
+ [subs="specialcharacters"]
370
+ [quote]
371
+ *Hey Jude*
372
+ EOS
373
+
374
+ output = render_embedded_string input
375
+ assert output.include?('*Hey Jude*')
376
+ end
182
377
  end
183
378
 
184
379
  context "special" do
185
380
  test "note multiline syntax" do
186
381
  Asciidoctor::ADMONITION_STYLES.each do |style|
187
- assert_xpath "//div[@class='admonitionblock']", render_string("[#{style}]\nThis is a winner.")
382
+ assert_xpath "//div[@class='admonitionblock #{style.downcase}']", render_string("[#{style}]\nThis is a winner.")
188
383
  end
189
384
  end
190
385
 
191
386
  test "note block syntax" do
192
387
  Asciidoctor::ADMONITION_STYLES.each do |style|
193
- assert_xpath "//div[@class='admonitionblock']", render_string("[#{style}]\n====\nThis is a winner.\n====")
388
+ assert_xpath "//div[@class='admonitionblock #{style.downcase}']", render_string("[#{style}]\n====\nThis is a winner.\n====")
194
389
  end
195
390
  end
196
391
 
197
392
  test "note inline syntax" do
198
393
  Asciidoctor::ADMONITION_STYLES.each do |style|
199
- assert_xpath "//div[@class='admonitionblock']", render_string("#{style}: This is important, fool!")
394
+ assert_xpath "//div[@class='admonitionblock #{style.downcase}']", render_string("#{style}: This is important, fool!")
200
395
  end
201
396
  end
202
397
 
@@ -0,0 +1,174 @@
1
+ require 'test_helper'
2
+
3
+ context 'Path Resolver' do
4
+ context 'Web Paths' do
5
+ def setup
6
+ @resolver = Asciidoctor::PathResolver.new
7
+ end
8
+
9
+ test 'target with absolute path' do
10
+ assert_equal '/images', @resolver.web_path('/images')
11
+ assert_equal '/images', @resolver.web_path('/images', '')
12
+ assert_equal '/images', @resolver.web_path('/images', nil)
13
+ end
14
+
15
+ test 'target with relative path' do
16
+ assert_equal 'images', @resolver.web_path('images')
17
+ assert_equal 'images', @resolver.web_path('images', '')
18
+ assert_equal 'images', @resolver.web_path('images', nil)
19
+ end
20
+
21
+ test 'target with path relative to current directory' do
22
+ assert_equal './images', @resolver.web_path('./images')
23
+ assert_equal './images', @resolver.web_path('./images', '')
24
+ assert_equal './images', @resolver.web_path('./images', nil)
25
+ end
26
+
27
+ test 'target with absolute path ignores start path' do
28
+ assert_equal '/images', @resolver.web_path('/images', 'foo')
29
+ assert_equal '/images', @resolver.web_path('/images', '/foo')
30
+ assert_equal '/images', @resolver.web_path('/images', './foo')
31
+ end
32
+
33
+ test 'target with relative path appended to start path' do
34
+ assert_equal 'assets/images', @resolver.web_path('images', 'assets')
35
+ assert_equal '/assets/images', @resolver.web_path('images', '/assets')
36
+ assert_equal './assets/images', @resolver.web_path('images', './assets')
37
+ end
38
+
39
+ test 'target with path relative to current directory appended to start path' do
40
+ assert_equal 'assets/images', @resolver.web_path('./images', 'assets')
41
+ assert_equal '/assets/images', @resolver.web_path('./images', '/assets')
42
+ assert_equal './assets/images', @resolver.web_path('./images', './assets')
43
+ end
44
+
45
+ test 'normalize target' do
46
+ assert_equal '../images', @resolver.web_path('../images/../images')
47
+ end
48
+
49
+ test 'append target to start path and normalize' do
50
+ assert_equal '../images', @resolver.web_path('../images/../images', '../images')
51
+ assert_equal '../../images', @resolver.web_path('../images', '..')
52
+ end
53
+
54
+ test 'normalize parent directory that follows root' do
55
+ assert_equal '/tiger.png', @resolver.web_path('/../tiger.png')
56
+ assert_equal '/tiger.png', @resolver.web_path('/../../tiger.png')
57
+ end
58
+
59
+ test 'uses start when target is empty' do
60
+ assert_equal 'assets/images', @resolver.web_path('', 'assets/images')
61
+ assert_equal 'assets/images', @resolver.web_path(nil, 'assets/images')
62
+ end
63
+
64
+ test 'posixfies windows paths' do
65
+ assert_equal '/images', @resolver.web_path('\\images')
66
+ assert_equal '../images', @resolver.web_path('..\\images')
67
+ assert_equal '/images', @resolver.web_path('\\..\\images')
68
+ assert_equal 'assets/images', @resolver.web_path('assets\\images')
69
+ assert_equal '../assets/images', @resolver.web_path('assets\\images', '..\\images\\..')
70
+ end
71
+ end
72
+
73
+ context 'System Paths' do
74
+ JAIL = '/home/doctor/docs'
75
+
76
+ def setup
77
+ @resolver = Asciidoctor::PathResolver.new
78
+ end
79
+
80
+ test 'prevents access to paths outside of jail' do
81
+ assert_equal "#{JAIL}/css", @resolver.system_path('../../../../../css', "#{JAIL}/assets/stylesheets", JAIL)
82
+ assert_equal "#{JAIL}/css", @resolver.system_path('/../../../../../css', "#{JAIL}/assets/stylesheets", JAIL)
83
+ assert_equal "#{JAIL}/css", @resolver.system_path('../../../css', '../../..', JAIL)
84
+ end
85
+
86
+ test 'throws exception for illegal path access if recover is false' do
87
+ begin
88
+ @resolver.system_path('../../../../../css', "#{JAIL}/assets/stylesheets", JAIL, :recover => false)
89
+ flunk 'Expecting SecurityError to be raised'
90
+ rescue SecurityError
91
+ end
92
+ end
93
+
94
+ test 'resolves start path if target is empty' do
95
+ assert_equal "#{JAIL}/assets/stylesheets", @resolver.system_path('', "#{JAIL}/assets/stylesheets", JAIL)
96
+ assert_equal "#{JAIL}/assets/stylesheets", @resolver.system_path(nil, "#{JAIL}/assets/stylesheets", JAIL)
97
+ end
98
+
99
+ test 'resolves start path if target is dot' do
100
+ assert_equal "#{JAIL}/assets/stylesheets", @resolver.system_path('.', "#{JAIL}/assets/stylesheets", JAIL)
101
+ assert_equal "#{JAIL}/assets/stylesheets", @resolver.system_path('./', "#{JAIL}/assets/stylesheets", JAIL)
102
+ end
103
+
104
+ test 'treats absolute target as relative when jail is specified' do
105
+ assert_equal "#{JAIL}/assets/stylesheets", @resolver.system_path('/', "#{JAIL}/assets/stylesheets", JAIL)
106
+ assert_equal "#{JAIL}/assets/stylesheets/foo", @resolver.system_path('/foo', "#{JAIL}/assets/stylesheets", JAIL)
107
+ assert_equal "#{JAIL}/assets/foo", @resolver.system_path('/../foo', "#{JAIL}/assets/stylesheets", JAIL)
108
+ end
109
+
110
+ test 'allows use of absolute target or start if resolved path is sub-path of jail' do
111
+ assert_equal "#{JAIL}/my/path", @resolver.system_path("#{JAIL}/my/path", '', JAIL)
112
+ assert_equal "#{JAIL}/my/path", @resolver.system_path("#{JAIL}/my/path", nil, JAIL)
113
+ assert_equal "#{JAIL}/my/path", @resolver.system_path('', "#{JAIL}/my/path", JAIL)
114
+ assert_equal "#{JAIL}/my/path", @resolver.system_path(nil, "#{JAIL}/my/path", JAIL)
115
+ assert_equal "#{JAIL}/my/path", @resolver.system_path('path', "#{JAIL}/my", JAIL)
116
+ end
117
+
118
+ test 'uses jail path if start path is empty' do
119
+ assert_equal "#{JAIL}/images/tiger.png", @resolver.system_path('images/tiger.png', '', JAIL)
120
+ assert_equal "#{JAIL}/images/tiger.png", @resolver.system_path('images/tiger.png', nil, JAIL)
121
+ end
122
+
123
+ test 'raises security error if start is not contained within jail' do
124
+ begin
125
+ @resolver.system_path('images/tiger.png', '/etc', JAIL)
126
+ flunk 'Expecting SecurityError to be raised'
127
+ rescue SecurityError
128
+ end
129
+
130
+ begin
131
+ @resolver.system_path('.', '/etc', JAIL)
132
+ flunk 'Expecting SecurityError to be raised'
133
+ rescue SecurityError
134
+ end
135
+ end
136
+
137
+ test 'resolves absolute directory if jail is not specified' do
138
+ assert_equal '/usr/share/stylesheet.css', @resolver.system_path('/usr/share/stylesheet.css', '/home/dallen/docs/assets/stylesheets')
139
+ end
140
+
141
+ test 'resolves ancestor directory of start if jail is not specified' do
142
+ assert_equal '/usr/share/stylesheet.css', @resolver.system_path('../../../../../usr/share/stylesheet.css', '/home/dallen/docs/assets/stylesheets')
143
+ end
144
+
145
+ test 'resolves absolute path if start is absolute and target is relative' do
146
+ assert_equal '/usr/share/assets/stylesheet.css', @resolver.system_path('assets/stylesheet.css', '/usr/share')
147
+ end
148
+
149
+ test 'resolves relative target relative to current directory if start is empty' do
150
+ pwd = File.expand_path(Dir.pwd)
151
+ assert_equal "#{pwd}/images/tiger.png", @resolver.system_path('images/tiger.png', '')
152
+ assert_equal "#{pwd}/images/tiger.png", @resolver.system_path('images/tiger.png', nil)
153
+ end
154
+
155
+ test 'resolves and normalizes start with target is empty' do
156
+ pwd = File.expand_path(Dir.pwd)
157
+ assert_equal '/home/doctor/docs', @resolver.system_path('', '/home/doctor/docs')
158
+ assert_equal '/home/doctor/docs', @resolver.system_path(nil, '/home/doctor/docs')
159
+ assert_equal "#{pwd}/assets/images", @resolver.system_path(nil, 'assets/images')
160
+ assert_equal "#{JAIL}/assets/images", @resolver.system_path('', '../assets/images', JAIL)
161
+ end
162
+
163
+ test 'posixfies windows paths' do
164
+ assert_equal "#{JAIL}/assets/css", @resolver.system_path('..\\css', 'assets\\stylesheets', JAIL)
165
+ end
166
+
167
+ test 'resolves windows paths when file separator is backlash' do
168
+ @resolver.file_separator = '\\'
169
+ assert_equal 'C:\\data\\docs', @resolver.system_path('..', "C:\\data\\docs\\assets", 'C:\\data\\docs')
170
+ assert_equal 'C:\\data\\docs', @resolver.system_path('..\\..', "C:\\data\\docs\\assets", 'C:\\data\\docs')
171
+ assert_equal 'C:\\data\\docs\\css', @resolver.system_path('..\\..\\css', "C:\\data\\docs\\assets", 'C:\\data\\docs')
172
+ end
173
+ end
174
+ end