nanoc 4.1.6 → 4.2.0b1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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