nanoc 4.1.6 → 4.2.0b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +2 -1
  4. data/NEWS.md +11 -4
  5. data/lib/nanoc/base/checksummer.rb +135 -46
  6. data/lib/nanoc/base/compilation/compiler.rb +18 -28
  7. data/lib/nanoc/base/compilation/dependency_tracker.rb +22 -32
  8. data/lib/nanoc/base/compilation/filter.rb +2 -4
  9. data/lib/nanoc/base/entities.rb +1 -0
  10. data/lib/nanoc/base/entities/content.rb +14 -3
  11. data/lib/nanoc/base/entities/document.rb +14 -6
  12. data/lib/nanoc/base/entities/item.rb +0 -31
  13. data/lib/nanoc/base/entities/item_rep.rb +1 -1
  14. data/lib/nanoc/base/entities/lazy_value.rb +36 -0
  15. data/lib/nanoc/base/entities/pattern.rb +3 -2
  16. data/lib/nanoc/base/entities/site.rb +2 -0
  17. data/lib/nanoc/base/memoization.rb +17 -10
  18. data/lib/nanoc/base/repos/compiled_content_cache.rb +1 -1
  19. data/lib/nanoc/base/repos/data_source.rb +10 -6
  20. data/lib/nanoc/base/services/executor.rb +22 -22
  21. data/lib/nanoc/base/services/item_rep_router.rb +4 -5
  22. data/lib/nanoc/base/views.rb +0 -1
  23. data/lib/nanoc/base/views/item_rep_view.rb +3 -9
  24. data/lib/nanoc/base/views/mixins/document_view_mixin.rb +4 -11
  25. data/lib/nanoc/base/views/view.rb +1 -0
  26. data/lib/nanoc/base/views/view_context.rb +5 -1
  27. data/lib/nanoc/cli/commands/compile.rb +0 -6
  28. data/lib/nanoc/data_sources.rb +5 -5
  29. data/lib/nanoc/data_sources/filesystem.rb +219 -90
  30. data/lib/nanoc/extra/checking/check.rb +1 -2
  31. data/lib/nanoc/extra/checking/checks.rb +2 -0
  32. data/lib/nanoc/extra/checking/checks/css.rb +6 -14
  33. data/lib/nanoc/extra/checking/checks/html.rb +6 -14
  34. data/lib/nanoc/extra/checking/checks/internal_links.rb +14 -3
  35. data/lib/nanoc/extra/checking/checks/w3c_validator.rb +28 -0
  36. data/lib/nanoc/extra/deployers/fog.rb +134 -78
  37. data/lib/nanoc/extra/link_collector.rb +14 -18
  38. data/lib/nanoc/filters/sass.rb +3 -3
  39. data/lib/nanoc/helpers.rb +1 -0
  40. data/lib/nanoc/helpers/capturing.rb +16 -58
  41. data/lib/nanoc/helpers/child_parent.rb +51 -0
  42. data/lib/nanoc/helpers/filtering.rb +0 -1
  43. data/lib/nanoc/helpers/html_escape.rb +5 -0
  44. data/lib/nanoc/helpers/link_to.rb +2 -0
  45. data/lib/nanoc/helpers/rendering.rb +3 -4
  46. data/lib/nanoc/rule_dsl/action_provider.rb +20 -4
  47. data/lib/nanoc/rule_dsl/recording_executor.rb +3 -1
  48. data/lib/nanoc/rule_dsl/rule_context.rb +0 -1
  49. data/lib/nanoc/rule_dsl/rule_memory_calculator.rb +4 -1
  50. data/lib/nanoc/spec.rb +217 -0
  51. data/lib/nanoc/version.rb +1 -1
  52. data/test/base/test_data_source.rb +4 -2
  53. data/test/base/test_dependency_tracker.rb +5 -11
  54. data/test/data_sources/test_filesystem.rb +605 -69
  55. data/test/extra/checking/checks/test_internal_links.rb +25 -0
  56. data/test/extra/deployers/test_fog.rb +0 -177
  57. data/test/filters/test_less.rb +9 -4
  58. data/test/helpers/test_capturing.rb +38 -212
  59. data/test/helpers/test_link_to.rb +0 -205
  60. data/test/helpers/test_xml_sitemap.rb +2 -1
  61. metadata +7 -12
  62. data/lib/nanoc/base/views/site_view.rb +0 -14
  63. data/lib/nanoc/data_sources/filesystem_unified.rb +0 -101
  64. data/test/data_sources/test_filesystem_unified.rb +0 -559
  65. data/test/helpers/test_breadcrumbs.rb +0 -60
  66. data/test/helpers/test_filtering.rb +0 -112
  67. data/test/helpers/test_html_escape.rb +0 -26
  68. data/test/helpers/test_rendering.rb +0 -147
  69. data/test/helpers/test_tagging.rb +0 -92
  70. data/test/helpers/test_text.rb +0 -18
@@ -1,4 +1,4 @@
1
1
  module Nanoc
2
2
  # The current Nanoc version.
3
- VERSION = '4.1.6'.freeze
3
+ VERSION = '4.2.0b1'.freeze
4
4
  end
@@ -33,18 +33,20 @@ class Nanoc::DataSourceTest < Nanoc::TestCase
33
33
  def test_new_item
34
34
  data_source = Nanoc::DataSource.new(nil, nil, nil, nil)
35
35
 
36
- item = data_source.new_item('stuff', { title: 'Stuff!' }, '/asdf/')
36
+ item = data_source.new_item('stuff', { title: 'Stuff!' }, '/asdf/', checksum_data: 'abcdef')
37
37
  assert_equal 'stuff', item.content.string
38
38
  assert_equal 'Stuff!', item.attributes[:title]
39
39
  assert_equal Nanoc::Identifier.new('/asdf/'), item.identifier
40
+ assert_equal 'abcdef', item.checksum_data
40
41
  end
41
42
 
42
43
  def test_new_layout
43
44
  data_source = Nanoc::DataSource.new(nil, nil, nil, nil)
44
45
 
45
- layout = data_source.new_layout('stuff', { title: 'Stuff!' }, '/asdf/')
46
+ layout = data_source.new_layout('stuff', { title: 'Stuff!' }, '/asdf/', checksum_data: 'abcdef')
46
47
  assert_equal 'stuff', layout.content.string
47
48
  assert_equal 'Stuff!', layout.attributes[:title]
48
49
  assert_equal Nanoc::Identifier.new('/asdf/'), layout.identifier
50
+ assert_equal 'abcdef', layout.checksum_data
49
51
  end
50
52
  end
@@ -86,23 +86,17 @@ class Nanoc::Int::DependencyTrackerTest < Nanoc::TestCase
86
86
  assert_contains_exactly [items[0]], store.objects_outdated_due_to(items[1])
87
87
  end
88
88
 
89
- def test_start_and_stop
90
- # Mock items
89
+ def test_enter_and_exit
91
90
  items = [mock, mock]
92
91
 
93
- # Create
94
92
  store = Nanoc::Int::DependencyStore.new(items)
95
93
  tracker = Nanoc::Int::DependencyTracker.new(store)
96
94
 
97
- # Start, do something and stop
98
- tracker.run do
99
- Nanoc::Int::NotificationCenter.post(:visit_started, items[0])
100
- Nanoc::Int::NotificationCenter.post(:visit_started, items[1])
101
- Nanoc::Int::NotificationCenter.post(:visit_ended, items[1])
102
- Nanoc::Int::NotificationCenter.post(:visit_ended, items[0])
103
- end
95
+ tracker.enter(items[0])
96
+ tracker.enter(items[1])
97
+ tracker.exit(items[1])
98
+ tracker.exit(items[0])
104
99
 
105
- # Verify dependencies
106
100
  assert_contains_exactly [items[1]], store.objects_causing_outdatedness_of(items[0])
107
101
  assert_empty store.objects_causing_outdatedness_of(items[1])
108
102
  end
@@ -1,29 +1,565 @@
1
1
  class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
2
- class SampleFilesystemDataSource < Nanoc::DataSource
3
- include Nanoc::DataSources::Filesystem
2
+ def new_data_source(params = nil)
3
+ # Mock site
4
+ site = Nanoc::Int::SiteLoader.new.new_empty
5
+
6
+ # Create data source
7
+ data_source = Nanoc::DataSources::Filesystem.new(site.config, nil, nil, params)
8
+
9
+ # Done
10
+ data_source
11
+ end
12
+
13
+ def test_load_objects
14
+ # Create data source
15
+ data_source = new_data_source
16
+
17
+ # Create a fake class
18
+ klass = Class.new do
19
+ attr_reader :stuff
20
+ def initialize(*stuff)
21
+ @stuff = stuff
22
+ end
23
+
24
+ def ==(other)
25
+ @stuff == other.stuff
26
+ end
27
+ end
28
+
29
+ # Create sample files
30
+ FileUtils.mkdir_p('foo')
31
+ FileUtils.mkdir_p('foo/a/b')
32
+ File.open('foo/bar.html', 'w') { |io| io.write("---\nnum: 1\n---\ntest 1") }
33
+ File.open('foo/b.c.html', 'w') { |io| io.write("---\nnum: 2\n---\ntest 2") }
34
+ File.open('foo/a/b/c.html', 'w') { |io| io.write("---\nnum: 3\n---\ntest 3") }
35
+ File.open('foo/ugly.html~', 'w') { |io| io.write("---\nnum: 4\n---\ntest 4") }
36
+ File.open('foo/ugly.html.orig', 'w') { |io| io.write("---\nnum: 5\n---\ntest 5") }
37
+ File.open('foo/ugly.html.rej', 'w') { |io| io.write("---\nnum: 6\n---\ntest 6") }
38
+ File.open('foo/ugly.html.bak', 'w') { |io| io.write("---\nnum: 7\n---\ntest 7") }
39
+
40
+ # Get expected and actual output
41
+ expected_out = [
42
+ klass.new(
43
+ 'test 1',
44
+ { 'num' => 1, :filename => 'foo/bar.html', :extension => 'html', mtime: File.mtime('foo/bar.html') },
45
+ '/bar/',
46
+ ),
47
+ klass.new(
48
+ 'test 2',
49
+ { 'num' => 2, :filename => 'foo/b.c.html', :extension => 'c.html', mtime: File.mtime('foo/b.c.html') },
50
+ '/b/',
51
+ ),
52
+ klass.new(
53
+ 'test 3',
54
+ { 'num' => 3, :filename => 'foo/a/b/c.html', :extension => 'html', mtime: File.mtime('foo/a/b/c.html') },
55
+ '/a/b/c/',
56
+ ),
57
+ ]
58
+ actual_out = data_source.send(:load_objects, 'foo', klass).sort_by { |i| i.stuff[0].string }
59
+
60
+ # Check
61
+ (0..expected_out.size - 1).each do |i|
62
+ assert_equal expected_out[i].stuff[0], actual_out[i].stuff[0].string, 'content must match'
63
+ assert_equal expected_out[i].stuff[2], actual_out[i].stuff[2], 'identifier must match'
64
+ ['num', :filename, :extension, :mtime].each do |key|
65
+ assert_equal expected_out[i].stuff[1][key], actual_out[i].stuff[1][key], "attribute key #{key} must match"
66
+ end
67
+ end
4
68
  end
5
69
 
6
- def test_items
70
+ def test_load_objects_with_same_extensions
7
71
  # Create data source
8
- data_source = SampleFilesystemDataSource.new(nil, nil, nil, nil)
72
+ data_source = new_data_source({ identifier_type: 'full' })
73
+
74
+ # Create a fake class
75
+ klass = Class.new do
76
+ attr_reader :stuff
77
+ def initialize(*stuff)
78
+ @stuff = stuff
79
+ end
80
+
81
+ def ==(other)
82
+ @stuff == other.stuff
83
+ end
84
+ end
85
+
86
+ # Create sample files
87
+ FileUtils.mkdir_p('foo')
88
+ File.open('foo/bar.html', 'w') { |io| io.write("---\nnum: 1\n---\ntest 1") }
89
+ File.open('foo/bar.md', 'w') { |io| io.write("---\nnum: 1\n---\ntest 1") }
9
90
 
10
91
  # Check
11
- data_source.expects(:load_objects).with('content', 'item', Nanoc::Int::Item)
12
- data_source.items
92
+ actual_out = data_source.send(:load_objects, 'foo', klass)
93
+ assert_equal 2, actual_out.size
13
94
  end
14
95
 
15
- def test_layouts
96
+ def test_load_binary_objects
16
97
  # Create data source
17
- data_source = SampleFilesystemDataSource.new(nil, nil, nil, nil)
98
+ data_source = new_data_source
99
+
100
+ # Create sample files
101
+ FileUtils.mkdir_p('foo')
102
+ File.open('foo/stuff.dat', 'w') { |io| io.write('random binary data') }
103
+
104
+ # Load
105
+ items = data_source.send(:load_objects, 'foo', Nanoc::Int::Item)
18
106
 
19
107
  # Check
20
- data_source.expects(:load_objects).with('layouts', 'layout', Nanoc::Int::Layout)
21
- data_source.layouts
108
+ assert_equal 1, items.size
109
+ assert items[0].content.binary?
110
+ assert_equal "#{Dir.getwd}/foo/stuff.dat", items[0].content.filename
111
+ assert_equal Nanoc::Int::BinaryContent, items[0].content.class
112
+ end
113
+
114
+ def test_load_layouts_with_nil_dir_name
115
+ # Create data source
116
+ data_source = new_data_source(layouts_dir: nil)
117
+
118
+ # Create sample files
119
+ FileUtils.mkdir_p('layouts')
120
+ File.write('layouts/stuff.txt', 'blah blah')
121
+
122
+ # Load
123
+ layouts = data_source.layouts
124
+
125
+ # Check
126
+ assert_empty(layouts)
127
+ end
128
+
129
+ def test_load_binary_layouts
130
+ # Create data source
131
+ data_source = new_data_source
132
+
133
+ # Create sample files
134
+ FileUtils.mkdir_p('foo')
135
+ File.open('foo/stuff.dat', 'w') { |io| io.write('random binary data') }
136
+
137
+ # Load
138
+ assert_raises(RuntimeError) do
139
+ data_source.send(:load_objects, 'foo', Nanoc::Int::Layout)
140
+ end
141
+ end
142
+
143
+ def test_identifier_for_filename_with_full_style_identifier
144
+ # Create data source
145
+ data_source = new_data_source({ identifier_type: 'full' })
146
+
147
+ # Get input and expected output
148
+ expected = {
149
+ '/foo' => Nanoc::Identifier.new('/foo', type: :full),
150
+ '/foo.html' => Nanoc::Identifier.new('/foo.html', type: :full),
151
+ '/foo/index.html' => Nanoc::Identifier.new('/foo/index.html', type: :full),
152
+ '/foo.html.erb' => Nanoc::Identifier.new('/foo.html.erb', type: :full),
153
+ }
154
+
155
+ # Check
156
+ expected.each_pair do |input, expected_output|
157
+ actual_output = data_source.send(:identifier_for_filename, input)
158
+ assert_equal(
159
+ expected_output, actual_output,
160
+ "identifier_for_filename(#{input.inspect}) should equal #{expected_output.inspect}, not #{actual_output.inspect}"
161
+ )
162
+ end
163
+ end
164
+
165
+ def test_identifier_for_filename_allowing_periods_in_identifiers
166
+ # Create data source
167
+ data_source = new_data_source(allow_periods_in_identifiers: true)
168
+
169
+ # Get input and expected output
170
+ expected = {
171
+ '/foo' => '/foo/',
172
+ '/foo.html' => '/foo/',
173
+ '/foo/index.html' => '/foo/',
174
+ '/foo.entry.html' => '/foo.entry/',
175
+ }
176
+
177
+ # Check
178
+ expected.each_pair do |input, expected_output|
179
+ actual_output = data_source.send(:identifier_for_filename, input)
180
+ assert_equal(
181
+ expected_output, actual_output,
182
+ "identifier_for_filename(#{input.inspect}) should equal #{expected_output.inspect}, not #{actual_output.inspect}"
183
+ )
184
+ end
185
+ end
186
+
187
+ def test_identifier_for_filename_disallowing_periods_in_identifiers
188
+ # Create data source
189
+ data_source = new_data_source
190
+
191
+ # Get input and expected output
192
+ expected = {
193
+ '/foo' => '/foo/',
194
+ '/foo.html' => '/foo/',
195
+ '/foo/index.html' => '/foo/',
196
+ '/foo.html.erb' => '/foo/',
197
+ }
198
+
199
+ # Check
200
+ expected.each_pair do |input, expected_output|
201
+ actual_output = data_source.send(:identifier_for_filename, input)
202
+ assert_equal(
203
+ expected_output, actual_output,
204
+ "identifier_for_filename(#{input.inspect}) should equal #{expected_output.inspect}, not #{actual_output.inspect}"
205
+ )
206
+ end
207
+ end
208
+
209
+ def test_identifier_for_filename_with_subfilename_allowing_periods_in_identifiers
210
+ expectations = {
211
+ 'foo/bar.yaml' => '/foo/bar/',
212
+ 'foo/quxbar.yaml' => '/foo/quxbar/',
213
+ 'foo/barqux.yaml' => '/foo/barqux/',
214
+ 'foo/quxbarqux.yaml' => '/foo/quxbarqux/',
215
+ 'foo/qux.bar.yaml' => '/foo/qux.bar/',
216
+ 'foo/bar.qux.yaml' => '/foo/bar.qux/',
217
+ 'foo/qux.bar.qux.yaml' => '/foo/qux.bar.qux/',
218
+ 'foo/index.yaml' => '/foo/',
219
+ 'index.yaml' => '/',
220
+ 'foo/blah_index.yaml' => '/foo/blah_index/',
221
+ }
222
+
223
+ data_source = new_data_source(allow_periods_in_identifiers: true)
224
+ expectations.each_pair do |meta_filename, expected_identifier|
225
+ content_filename = meta_filename.sub(/yaml$/, 'html')
226
+ [meta_filename, content_filename].each do |filename|
227
+ assert_equal(
228
+ expected_identifier,
229
+ data_source.instance_eval { identifier_for_filename(filename) },
230
+ )
231
+ end
232
+ end
233
+ end
234
+
235
+ def test_identifier_for_filename_with_subfilename_disallowing_periods_in_identifiers
236
+ expectations = {
237
+ 'foo/bar.yaml' => '/foo/bar/',
238
+ 'foo/quxbar.yaml' => '/foo/quxbar/',
239
+ 'foo/barqux.yaml' => '/foo/barqux/',
240
+ 'foo/quxbarqux.yaml' => '/foo/quxbarqux/',
241
+ 'foo/qux.bar.yaml' => '/foo/qux/',
242
+ 'foo/bar.qux.yaml' => '/foo/bar/',
243
+ 'foo/qux.bar.qux.yaml' => '/foo/qux/',
244
+ 'foo/index.yaml' => '/foo/',
245
+ 'index.yaml' => '/',
246
+ 'foo/blah_index.yaml' => '/foo/blah_index/',
247
+ }
248
+
249
+ data_source = new_data_source
250
+ expectations.each_pair do |meta_filename, expected_identifier|
251
+ content_filename = meta_filename.sub(/yaml$/, 'html')
252
+ [meta_filename, content_filename].each do |filename|
253
+ assert_equal(
254
+ expected_identifier,
255
+ data_source.instance_eval { identifier_for_filename(filename) },
256
+ )
257
+ end
258
+ end
259
+ end
260
+
261
+ def test_identifier_for_filename_with_index_filenames_allowing_periods_in_identifier
262
+ expected = {
263
+ '/index.html.erb' => '/index.html/',
264
+ '/index.html' => '/',
265
+ '/index' => '/',
266
+ '/foo/index.html.erb' => '/foo/index.html/',
267
+ '/foo/index.html' => '/foo/',
268
+ '/foo/index' => '/foo/',
269
+ }
270
+
271
+ data_source = new_data_source(allow_periods_in_identifiers: true)
272
+ expected.each_pair do |input, expected_output|
273
+ actual_output = data_source.send(:identifier_for_filename, input)
274
+ assert_equal(
275
+ expected_output, actual_output,
276
+ "identifier_for_filename(#{input.inspect}) should equal #{expected_output.inspect}, not #{actual_output.inspect}"
277
+ )
278
+ end
279
+ end
280
+
281
+ def test_identifier_for_filename_with_index_filenames_disallowing_periods_in_identifier
282
+ expected = {
283
+ '/index.html.erb' => '/',
284
+ '/index.html' => '/',
285
+ '/index' => '/',
286
+ '/foo/index.html.erb' => '/foo/',
287
+ '/foo/index.html' => '/foo/',
288
+ '/foo/index' => '/foo/',
289
+ }
290
+
291
+ data_source = new_data_source
292
+ expected.each_pair do |input, expected_output|
293
+ actual_output = data_source.send(:identifier_for_filename, input)
294
+ assert_equal(
295
+ expected_output, actual_output,
296
+ "identifier_for_filename(#{input.inspect}) should equal #{expected_output.inspect}, not #{actual_output.inspect}"
297
+ )
298
+ end
299
+ end
300
+
301
+ def test_load_objects_allowing_periods_in_identifiers
302
+ # Create data source
303
+ data_source = new_data_source(allow_periods_in_identifiers: true)
304
+
305
+ # Create a fake class
306
+ klass = Class.new do
307
+ attr_reader :stuff
308
+ def initialize(*stuff)
309
+ @stuff = stuff
310
+ end
311
+
312
+ def ==(other)
313
+ @stuff == other.stuff
314
+ end
315
+ end
316
+
317
+ # Create sample files
318
+ FileUtils.mkdir_p('foo')
319
+ FileUtils.mkdir_p('foo/a/b')
320
+ File.open('foo/a/b/c.yaml', 'w') { |io| io.write("---\nnum: 1\n") }
321
+ File.open('foo/b.c.yaml', 'w') { |io| io.write("---\nnum: 2\n") }
322
+ File.open('foo/b.c.html', 'w') { |io| io.write('test 2') }
323
+ File.open('foo/car.html', 'w') { |io| io.write('test 3') }
324
+ File.open('foo/ugly.yaml~', 'w') { |io| io.write('blah') }
325
+ File.open('foo/ugly.html~', 'w') { |io| io.write('blah') }
326
+ File.open('foo/ugly.html.orig', 'w') { |io| io.write('blah') }
327
+ File.open('foo/ugly.html.rej', 'w') { |io| io.write('blah') }
328
+ File.open('foo/ugly.html.bak', 'w') { |io| io.write('blah') }
329
+
330
+ # Get expected output
331
+ expected_out = [
332
+ klass.new(
333
+ '',
334
+ {
335
+ 'num' => 1,
336
+ :content_filename => nil,
337
+ :meta_filename => 'foo/a/b/c.yaml',
338
+ :extension => nil,
339
+ :file => nil,
340
+ mtime: File.mtime('foo/a/b/c.yaml'),
341
+ },
342
+ '/a/b/c/',
343
+ ),
344
+ klass.new(
345
+ 'test 2',
346
+ {
347
+ 'num' => 2,
348
+ :content_filename => 'foo/b.c.html',
349
+ :meta_filename => 'foo/b.c.yaml',
350
+ :extension => 'html',
351
+ :file => File.open('foo/b.c.html'),
352
+ mtime: File.mtime('foo/b.c.html') > File.mtime('foo/b.c.yaml') ? File.mtime('foo/b.c.html') : File.mtime('foo/b.c.yaml'),
353
+ },
354
+ '/b.c/',
355
+ ),
356
+ klass.new(
357
+ 'test 3',
358
+ {
359
+ content_filename: 'foo/car.html',
360
+ meta_filename: nil,
361
+ extension: 'html',
362
+ file: File.open('foo/car.html'),
363
+ mtime: File.mtime('foo/car.html'),
364
+ },
365
+ '/car/',
366
+ ),
367
+ ]
368
+
369
+ # Get actual output ordered by identifier
370
+ actual_out = data_source.send(:load_objects, 'foo', klass).sort_by { |i| i.stuff[2] }
371
+
372
+ # Check
373
+ (0..expected_out.size - 1).each do |i|
374
+ assert_equal expected_out[i].stuff[0], actual_out[i].stuff[0].string, 'content must match'
375
+ assert_equal expected_out[i].stuff[2], actual_out[i].stuff[2], 'identifier must match'
376
+
377
+ ['num', :content_filename, :meta_filename, :extension, :mtime].each do |key|
378
+ assert_equal expected_out[i].stuff[1][key], actual_out[i].stuff[1][key], "attribute key #{key} must match"
379
+ end
380
+ end
381
+ end
382
+
383
+ def test_load_objects_disallowing_periods_in_identifiers
384
+ # Create data source
385
+ data_source = new_data_source
386
+
387
+ # Create a fake class
388
+ klass = Class.new do
389
+ attr_reader :stuff
390
+ def initialize(*stuff)
391
+ @stuff = stuff
392
+ end
393
+
394
+ def ==(other)
395
+ @stuff == other.stuff
396
+ end
397
+ end
398
+
399
+ # Create sample files
400
+ FileUtils.mkdir_p('foo')
401
+ FileUtils.mkdir_p('foo/a/b')
402
+ File.open('foo/a/b/c.yaml', 'w') { |io| io.write("---\nnum: 1\n") }
403
+ File.open('foo/b.yaml', 'w') { |io| io.write("---\nnum: 2\n") }
404
+ File.open('foo/b.html.erb', 'w') { |io| io.write('test 2') }
405
+ File.open('foo/car.html', 'w') { |io| io.write('test 3') }
406
+ File.open('foo/ugly.yaml~', 'w') { |io| io.write('blah') }
407
+ File.open('foo/ugly.html~', 'w') { |io| io.write('blah') }
408
+ File.open('foo/ugly.html.orig', 'w') { |io| io.write('blah') }
409
+ File.open('foo/ugly.html.rej', 'w') { |io| io.write('blah') }
410
+ File.open('foo/ugly.html.bak', 'w') { |io| io.write('blah') }
411
+
412
+ # Get expected output
413
+ expected_out = [
414
+ klass.new(
415
+ '',
416
+ {
417
+ 'num' => 1,
418
+ :content_filename => nil,
419
+ :meta_filename => 'foo/a/b/c.yaml',
420
+ :extension => nil,
421
+ :file => nil,
422
+ mtime: File.mtime('foo/a/b/c.yaml'),
423
+ },
424
+ '/a/b/c/',
425
+ ),
426
+ klass.new(
427
+ 'test 2',
428
+ {
429
+ 'num' => 2,
430
+ :content_filename => 'foo/b.html.erb',
431
+ :meta_filename => 'foo/b.yaml',
432
+ :extension => 'html.erb',
433
+ :file => File.open('foo/b.html.erb'),
434
+ mtime: File.mtime('foo/b.html.erb') > File.mtime('foo/b.yaml') ? File.mtime('foo/b.html.erb') : File.mtime('foo/b.yaml'),
435
+ },
436
+ '/b/',
437
+ ),
438
+ klass.new(
439
+ 'test 3',
440
+ {
441
+ content_filename: 'foo/car.html',
442
+ meta_filename: nil,
443
+ extension: 'html',
444
+ file: File.open('foo/car.html'),
445
+ mtime: File.mtime('foo/car.html'),
446
+ },
447
+ '/car/',
448
+ ),
449
+ ]
450
+
451
+ # Get actual output ordered by identifier
452
+ actual_out = data_source.send(:load_objects, 'foo', klass).sort_by { |i| i.stuff[2] }
453
+
454
+ # Check
455
+ (0..expected_out.size - 1).each do |i|
456
+ assert_equal expected_out[i].stuff[0], actual_out[i].stuff[0].string, 'content must match'
457
+ assert_equal expected_out[i].stuff[2], actual_out[i].stuff[2], 'identifier must match'
458
+
459
+ ['num', :content_filename, :meta_filename, :extension, :mtime].each do |key|
460
+ assert_equal expected_out[i].stuff[1][key], actual_out[i].stuff[1][key], "attribute key #{key} must match"
461
+ end
462
+ end
463
+ end
464
+
465
+ def test_load_objects_correct_identifier_with_separate_yaml_file
466
+ data_source = new_data_source({ identifier_type: 'full' })
467
+
468
+ FileUtils.mkdir_p('foo')
469
+ File.write('foo/donkey.jpeg', 'data')
470
+ File.write('foo/donkey.yaml', "---\nalt: Donkey\n")
471
+
472
+ objects = data_source.send(:load_objects, 'foo', Nanoc::Int::Item)
473
+ assert_equal 1, objects.size
474
+ assert_equal '/donkey.jpeg', objects.first.identifier.to_s
475
+ end
476
+
477
+ def test_filename_for
478
+ data_source = new_data_source
479
+
480
+ assert_equal '/foo.bar', data_source.send(:filename_for, '/foo', 'bar')
481
+ assert_equal '/foo.bar.baz', data_source.send(:filename_for, '/foo', 'bar.baz')
482
+ assert_equal '/foo', data_source.send(:filename_for, '/foo', '')
483
+ assert_equal nil, data_source.send(:filename_for, '/foo', nil)
484
+ end
485
+
486
+ def test_compile_huge_site
487
+ if_implemented do
488
+ # Create data source
489
+ data_source = new_data_source
490
+
491
+ # Create a lot of items
492
+ count = Process.getrlimit(Process::RLIMIT_NOFILE)[0] + 5
493
+ count.times do |i|
494
+ FileUtils.mkdir_p("content/#{i}")
495
+ File.open("content/#{i}/#{i}.html", 'w') { |io| io << "This is item #{i}." }
496
+ File.open("content/#{i}/#{i}.yaml", 'w') { |io| io << "title: Item #{i}" }
497
+ end
498
+
499
+ # Read all items
500
+ data_source.items
501
+ end
502
+ end
503
+
504
+ def test_compile_iso_8859_1_site
505
+ # Check encoding
506
+ unless ''.respond_to?(:encode)
507
+ skip 'Test only works on 1.9.x'
508
+ return
509
+ end
510
+
511
+ # Create data source
512
+ data_source = new_data_source
513
+
514
+ # Create item
515
+ FileUtils.mkdir_p('content')
516
+ File.open('content/foo.md', 'w') { |io| io << 'Hëllö' }
517
+
518
+ # Parse
519
+ begin
520
+ original_default_external_encoding = Encoding.default_external
521
+ Encoding.default_external = 'ISO-8859-1'
522
+
523
+ items = data_source.items
524
+
525
+ assert_equal 1, items.size
526
+ assert_equal Encoding.find('UTF-8'), items[0].content.string.encoding
527
+ ensure
528
+ Encoding.default_external = original_default_external_encoding
529
+ end
530
+ end
531
+
532
+ def test_compile_iso_8859_1_site_with_explicit_encoding
533
+ # Check encoding
534
+ unless ''.respond_to?(:encode)
535
+ skip 'Test only works on 1.9.x'
536
+ return
537
+ end
538
+
539
+ # Create data source
540
+ data_source = new_data_source({})
541
+ data_source.config[:encoding] = 'ISO-8859-1'
542
+
543
+ # Create item
544
+ begin
545
+ original_default_external_encoding = Encoding.default_external
546
+ Encoding.default_external = 'ISO-8859-1'
547
+
548
+ FileUtils.mkdir_p('content')
549
+ File.open('content/foo.md', 'w') { |io| io << 'Hëllö' }
550
+ ensure
551
+ Encoding.default_external = original_default_external_encoding
552
+ end
553
+
554
+ # Parse
555
+ items = data_source.items
556
+ assert_equal 1, items.size
557
+ assert_equal Encoding.find('UTF-8'), items[0].content.string.encoding
22
558
  end
23
559
 
24
560
  def test_all_split_files_in_allowing_periods_in_identifiers
25
561
  # Create data source
26
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, { allow_periods_in_identifiers: true })
562
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, { allow_periods_in_identifiers: true })
27
563
 
28
564
  # Write sample files
29
565
  FileUtils.mkdir_p('foo')
@@ -50,7 +586,7 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
50
586
 
51
587
  def test_all_split_files_in_disallowing_periods_in_identifiers
52
588
  # Create data source
53
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
589
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
54
590
 
55
591
  # Write sample files
56
592
  FileUtils.mkdir_p('foo')
@@ -77,7 +613,7 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
77
613
 
78
614
  def test_all_split_files_in_with_multiple_dirs
79
615
  # Create data source
80
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
616
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
81
617
 
82
618
  # Write sample files
83
619
  %w( aaa/foo.html bbb/foo.html ccc/foo.html ).each do |filename|
@@ -97,7 +633,7 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
97
633
  def test_all_split_files_in_with_same_extensions
98
634
  # Create data source
99
635
  config = { identifier_type: 'full' }
100
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, config)
636
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, config)
101
637
 
102
638
  # Write sample files
103
639
  %w( stuff/foo.html stuff/foo.md stuff/foo.yaml ).each do |filename|
@@ -116,7 +652,7 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
116
652
 
117
653
  def test_all_split_files_in_with_multiple_content_files
118
654
  # Create data source
119
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
655
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
120
656
 
121
657
  # Write sample files
122
658
  %w( foo.html foo.xhtml foo.txt foo.yaml bar.html qux.yaml ).each do |filename|
@@ -131,7 +667,7 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
131
667
 
132
668
  def test_basename_of_allowing_periods_in_identifiers
133
669
  # Create data source
134
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, { allow_periods_in_identifiers: true })
670
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, { allow_periods_in_identifiers: true })
135
671
 
136
672
  # Get input and expected output
137
673
  expected = {
@@ -161,7 +697,7 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
161
697
 
162
698
  def test_basename_of_disallowing_periods_in_identifiers
163
699
  # Create data source
164
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
700
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
165
701
 
166
702
  # Get input and expected output
167
703
  expected = {
@@ -191,7 +727,7 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
191
727
 
192
728
  def test_ext_of_allowing_periods_in_identifiers
193
729
  # Create data source
194
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, { allow_periods_in_identifiers: true })
730
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, { allow_periods_in_identifiers: true })
195
731
 
196
732
  # Get input and expected output
197
733
  expected = {
@@ -221,7 +757,7 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
221
757
 
222
758
  def test_ext_of_disallowing_periods_in_identifiers
223
759
  # Create data source
224
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
760
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
225
761
 
226
762
  # Get input and expected output
227
763
  expected = {
@@ -258,12 +794,12 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
258
794
  end
259
795
 
260
796
  # Create data source
261
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
797
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
262
798
 
263
799
  # Parse it
264
- result = data_source.instance_eval { parse('test.html', nil, 'foobar') }
265
- assert_equal({ 'foo' => 'bar' }, result[0])
266
- assert_equal('', result[1])
800
+ result = data_source.instance_eval { parse('test.html', nil) }
801
+ assert_equal({ 'foo' => 'bar' }, result.attributes)
802
+ assert_equal('', result.content)
267
803
  end
268
804
 
269
805
  def test_parse_embedded_meta_only_2
@@ -275,12 +811,12 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
275
811
  end
276
812
 
277
813
  # Create data source
278
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
814
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
279
815
 
280
816
  # Parse it
281
- result = data_source.instance_eval { parse('test.html', nil, 'foobar') }
282
- assert_equal({ 'foo' => 'bar' }, result[0])
283
- assert_equal('', result[1])
817
+ result = data_source.instance_eval { parse('test.html', nil) }
818
+ assert_equal({ 'foo' => 'bar' }, result.attributes)
819
+ assert_equal('', result.content)
284
820
  end
285
821
 
286
822
  def test_parse_embedded_meta_only_3
@@ -292,12 +828,12 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
292
828
  end
293
829
 
294
830
  # Create data source
295
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
831
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
296
832
 
297
833
  # Parse it
298
- result = data_source.instance_eval { parse('test.html', nil, 'foobar') }
299
- assert_equal({ 'foo' => 'bar' }, result[0])
300
- assert_equal('', result[1])
834
+ result = data_source.instance_eval { parse('test.html', nil) }
835
+ assert_equal({ 'foo' => 'bar' }, result.attributes)
836
+ assert_equal('', result.content)
301
837
  end
302
838
 
303
839
  def test_parse_embedded_invalid_2
@@ -308,11 +844,11 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
308
844
  end
309
845
 
310
846
  # Create data source
311
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
847
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
312
848
 
313
849
  # Parse it
314
850
  assert_raises(RuntimeError) do
315
- data_source.instance_eval { parse('test.html', nil, 'foobar') }
851
+ data_source.instance_eval { parse('test.html', nil) }
316
852
  end
317
853
  end
318
854
 
@@ -325,12 +861,12 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
325
861
  end
326
862
 
327
863
  # Create data source
328
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
864
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
329
865
 
330
866
  # Parse it
331
- result = data_source.instance_eval { parse('test.html', nil, 'foobar') }
332
- assert_equal(File.read('test.html'), result[1])
333
- assert_equal({}, result[0])
867
+ result = data_source.instance_eval { parse('test.html', nil) }
868
+ assert_equal(File.read('test.html'), result.content)
869
+ assert_equal({}, result.attributes)
334
870
  end
335
871
 
336
872
  def test_parse_embedded_full_meta
@@ -343,12 +879,12 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
343
879
  end
344
880
 
345
881
  # Create data source
346
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
882
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
347
883
 
348
884
  # Parse it
349
- result = data_source.instance_eval { parse('test.html', nil, 'foobar') }
350
- assert_equal({ 'foo' => 'bar' }, result[0])
351
- assert_equal(" \t\n blah blah\n", result[1])
885
+ result = data_source.instance_eval { parse('test.html', nil) }
886
+ assert_equal({ 'foo' => 'bar' }, result.attributes)
887
+ assert_equal(" \t\n blah blah\n", result.content)
352
888
  end
353
889
 
354
890
  def test_parse_embedded_with_extra_spaces
@@ -361,12 +897,12 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
361
897
  end
362
898
 
363
899
  # Create data source
364
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
900
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
365
901
 
366
902
  # Parse it
367
- result = data_source.instance_eval { parse('test.html', nil, 'foobar') }
368
- assert_equal({ 'foo' => 'bar' }, result[0])
369
- assert_equal(" blah blah\n", result[1])
903
+ result = data_source.instance_eval { parse('test.html', nil) }
904
+ assert_equal({ 'foo' => 'bar' }, result.attributes)
905
+ assert_equal(" blah blah\n", result.content)
370
906
  end
371
907
 
372
908
  def test_parse_embedded_empty_meta
@@ -379,12 +915,12 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
379
915
  end
380
916
 
381
917
  # Create data source
382
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
918
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
383
919
 
384
920
  # Parse it
385
- result = data_source.instance_eval { parse('test.html', nil, 'foobar') }
386
- assert_equal({}, result[0])
387
- assert_equal("\nblah blah\n-----", result[1])
921
+ result = data_source.instance_eval { parse('test.html', nil) }
922
+ assert_equal({}, result.attributes)
923
+ assert_equal("\nblah blah\n-----", result.content)
388
924
  end
389
925
 
390
926
  def test_parse_utf8_bom
@@ -396,11 +932,11 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
396
932
  io.write "content goes here\n"
397
933
  end
398
934
 
399
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, encoding: 'utf-8')
935
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, encoding: 'utf-8')
400
936
 
401
- result = data_source.instance_eval { parse('test.html', nil, 'foobar') }
402
- assert_equal({ 'utf8bomawareness' => 'high' }, result[0])
403
- assert_equal("content goes here\n", result[1])
937
+ result = data_source.instance_eval { parse('test.html', nil) }
938
+ assert_equal({ 'utf8bomawareness' => 'high' }, result.attributes)
939
+ assert_equal("content goes here\n", result.content)
404
940
  end
405
941
 
406
942
  def test_parse_embedded_no_meta
@@ -412,12 +948,12 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
412
948
  File.open('test.html', 'w') { |io| io.write(content) }
413
949
 
414
950
  # Create data source
415
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
951
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
416
952
 
417
953
  # Parse it
418
- result = data_source.instance_eval { parse('test.html', nil, 'foobar') }
419
- assert_equal({}, result[0])
420
- assert_equal(content, result[1])
954
+ result = data_source.instance_eval { parse('test.html', nil) }
955
+ assert_equal({}, result.attributes)
956
+ assert_equal(content, result.content)
421
957
  end
422
958
 
423
959
  def test_parse_embedded_diff
@@ -430,12 +966,12 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
430
966
  File.open('test.html', 'w') { |io| io.write(content) }
431
967
 
432
968
  # Create data source
433
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
969
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
434
970
 
435
971
  # Parse it
436
- result = data_source.instance_eval { parse('test.html', nil, 'foobar') }
437
- assert_equal({}, result[0])
438
- assert_equal(content, result[1])
972
+ result = data_source.instance_eval { parse('test.html', nil) }
973
+ assert_equal({}, result.attributes)
974
+ assert_equal(content, result.content)
439
975
  end
440
976
 
441
977
  def test_parse_external
@@ -444,12 +980,12 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
444
980
  File.open('test.yaml', 'w') { |io| io.write('foo: bar') }
445
981
 
446
982
  # Create data source
447
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
983
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
448
984
 
449
985
  # Parse it
450
- result = data_source.instance_eval { parse('test.html', 'test.yaml', 'foobar') }
451
- assert_equal({ 'foo' => 'bar' }, result[0])
452
- assert_equal('blah blah', result[1])
986
+ result = data_source.instance_eval { parse('test.html', 'test.yaml') }
987
+ assert_equal({ 'foo' => 'bar' }, result.attributes)
988
+ assert_equal('blah blah', result.content)
453
989
  end
454
990
 
455
991
  def test_parse_internal_bad_metadata
@@ -461,10 +997,10 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
461
997
 
462
998
  File.open('test.html', 'w') { |io| io.write(content) }
463
999
 
464
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
1000
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
465
1001
 
466
1002
  assert_raises(Nanoc::DataSources::Filesystem::InvalidMetadataError) do
467
- data_source.instance_eval { parse('test.html', nil, 'foobar') }
1003
+ data_source.instance_eval { parse('test.html', nil) }
468
1004
  end
469
1005
  end
470
1006
 
@@ -472,10 +1008,10 @@ class Nanoc::DataSources::FilesystemTest < Nanoc::TestCase
472
1008
  File.open('test.html', 'w') { |io| io.write('blah blah') }
473
1009
  File.open('test.yaml', 'w') { |io| io.write('Hello world!') }
474
1010
 
475
- data_source = Nanoc::DataSources::FilesystemUnified.new(nil, nil, nil, nil)
1011
+ data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil)
476
1012
 
477
1013
  assert_raises(Nanoc::DataSources::Filesystem::InvalidMetadataError) do
478
- data_source.instance_eval { parse('test.html', 'test.yaml', 'foobar') }
1014
+ data_source.instance_eval { parse('test.html', 'test.yaml') }
479
1015
  end
480
1016
  end
481
1017
  end