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,211 +1,6 @@
1
1
  class Nanoc::Helpers::LinkToTest < Nanoc::TestCase
2
2
  include Nanoc::Helpers::LinkTo
3
3
 
4
- def test_link_to_with_path
5
- assert_equal(
6
- '<a href="/foo/">Foo</a>',
7
- link_to('Foo', '/foo/'),
8
- )
9
- end
10
-
11
- def test_link_to_with_item_without_reps_view
12
- target = Nanoc::ItemWithoutRepsView.new(mock, {})
13
- target.stubs(:path).returns('/bar/')
14
-
15
- assert_equal(
16
- '<a href="/bar/">Bar</a>',
17
- link_to('Bar', target),
18
- )
19
- end
20
-
21
- def test_link_to_with_item_with_reps_view
22
- target = Nanoc::ItemWithRepsView.new(mock, {})
23
- target.stubs(:path).returns('/bar/')
24
-
25
- assert_equal(
26
- '<a href="/bar/">Bar</a>',
27
- link_to('Bar', target),
28
- )
29
- end
30
-
31
- def test_link_to_with_item_rep_view
32
- target = Nanoc::ItemRepView.new(mock, {})
33
- target.stubs(:path).returns('/bar/')
34
-
35
- assert_equal(
36
- '<a href="/bar/">Bar</a>',
37
- link_to('Bar', target),
38
- )
39
- end
40
-
41
- def test_link_to_with_attributes
42
- # Check
43
- assert_equal(
44
- '<a title="Dis mai foo!" href="/foo/">Foo</a>',
45
- link_to('Foo', '/foo/', title: 'Dis mai foo!'),
46
- )
47
- end
48
-
49
- def test_link_to_escape
50
- # Check
51
- assert_equal(
52
- '<a title="Foo &amp; Bar" href="/foo&amp;bar/">Foo &amp; Bar</a>',
53
- link_to('Foo &amp; Bar', '/foo&bar/', title: 'Foo & Bar'),
54
- )
55
- end
56
-
57
- def test_link_to_to_nil_item_or_item_rep
58
- target = Nanoc::ItemRepView.new(mock, {})
59
- target.stubs(:path).returns(nil)
60
-
61
- assert_raises RuntimeError do
62
- link_to('Some Text', target)
63
- end
64
- end
65
-
66
- def test_link_to_unless_current_current
67
- # Create item
68
- @item_rep = mock
69
- @item_rep.stubs(:path).returns('/foo/')
70
-
71
- # Check
72
- assert_equal(
73
- '<span class="active">Bar</span>',
74
- link_to_unless_current('Bar', @item_rep),
75
- )
76
- ensure
77
- @item = nil
78
- end
79
-
80
- def test_link_to_unless_current_not_current
81
- # Create item
82
- @item_rep = mock
83
- @item_rep.stubs(:path).returns('/foo/')
84
-
85
- # Check
86
- assert_equal(
87
- '<a href="/abc/xyz/">Bar</a>',
88
- link_to_unless_current('Bar', '/abc/xyz/'),
89
- )
90
- end
91
-
92
- def test_relative_path_to_with_self
93
- # Mock item
94
- @item_rep = mock
95
- @item_rep.stubs(:path).returns('/foo/bar/baz/')
96
-
97
- # Test
98
- assert_equal(
99
- './',
100
- relative_path_to('/foo/bar/baz/'),
101
- )
102
- end
103
-
104
- def test_relative_path_to_with_root
105
- # Mock item
106
- @item_rep = mock
107
- @item_rep.stubs(:path).returns('/foo/bar/baz/')
108
-
109
- # Test
110
- assert_equal(
111
- '../../../',
112
- relative_path_to('/'),
113
- )
114
- end
115
-
116
- def test_relative_path_to_file
117
- # Mock item
118
- @item_rep = mock
119
- @item_rep.stubs(:path).returns('/foo/bar/baz/')
120
-
121
- # Test
122
- assert_equal(
123
- '../../quux',
124
- relative_path_to('/foo/quux'),
125
- )
126
- end
127
-
128
- def test_relative_path_to_dir
129
- # Mock item
130
- @item_rep = mock
131
- @item_rep.stubs(:path).returns('/foo/bar/baz/')
132
-
133
- # Test
134
- assert_equal(
135
- '../../quux/',
136
- relative_path_to('/foo/quux/'),
137
- )
138
- end
139
-
140
- def test_relative_path_to_rep
141
- # Mock self
142
- @item_rep = mock
143
- @item_rep.stubs(:path).returns('/foo/bar/baz/')
144
-
145
- # Mock other
146
- other_item_rep = mock
147
- other_item_rep.stubs(:path).returns('/foo/quux/')
148
-
149
- # Test
150
- assert_equal(
151
- '../../quux/',
152
- relative_path_to(other_item_rep),
153
- )
154
- end
155
-
156
- def test_relative_path_to_item
157
- # Mock self
158
- @item_rep = mock
159
- @item_rep.stubs(:path).returns('/foo/bar/baz/')
160
-
161
- # Mock other
162
- other_item = mock
163
- other_item.stubs(:path).returns('/foo/quux/')
164
-
165
- # Test
166
- assert_equal(
167
- '../../quux/',
168
- relative_path_to(other_item),
169
- )
170
- end
171
-
172
- def test_relative_path_to_to_nil
173
- # Mock self
174
- @item_rep = mock
175
- @item_rep.stubs(:path).returns(nil)
176
-
177
- # Mock other
178
- other_item_rep = mock
179
- other_item_rep.stubs(:path).returns('/foo/quux/')
180
-
181
- # Test
182
- assert_raises RuntimeError do
183
- relative_path_to(other_item_rep)
184
- end
185
- end
186
-
187
- def test_relative_path_to_from_nil
188
- # Mock self
189
- @item_rep = mock
190
- @item_rep.stubs(:path).returns('/foo/quux/')
191
-
192
- # Mock other
193
- other_item_rep = mock
194
- other_item_rep.stubs(:path).returns(nil)
195
-
196
- # Test
197
- assert_raises RuntimeError do
198
- relative_path_to(other_item_rep)
199
- end
200
- end
201
-
202
- def test_relative_path_to_to_windows_path
203
- @item_rep = mock
204
- @item_rep.stubs(:path).returns('/foo/quux/')
205
-
206
- assert_equal '//mydomain/tahontaenrat', relative_path_to('//mydomain/tahontaenrat')
207
- end
208
-
209
4
  def test_examples_link_to
210
5
  # Parse
211
6
  YARD.parse(LIB_DIR + '/nanoc/helpers/link_to.rb')
@@ -5,7 +5,8 @@ class Nanoc::Helpers::XMLSitemapTest < Nanoc::TestCase
5
5
  super
6
6
 
7
7
  @reps = Nanoc::Int::ItemRepRepo.new
8
- @view_context = Nanoc::ViewContext.new(reps: @reps, items: nil)
8
+ dependency_tracker = Nanoc::Int::DependencyTracker.new(nil)
9
+ @view_context = Nanoc::ViewContext.new(reps: @reps, items: nil, dependency_tracker: dependency_tracker, compiler: :__irrelevant__)
9
10
 
10
11
  @items = nil
11
12
  @item = nil
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nanoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.6
4
+ version: 4.2.0b1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Defreyne
@@ -96,6 +96,7 @@ files:
96
96
  - lib/nanoc/base/entities/item.rb
97
97
  - lib/nanoc/base/entities/item_rep.rb
98
98
  - lib/nanoc/base/entities/layout.rb
99
+ - lib/nanoc/base/entities/lazy_value.rb
99
100
  - lib/nanoc/base/entities/pattern.rb
100
101
  - lib/nanoc/base/entities/rule_memory.rb
101
102
  - lib/nanoc/base/entities/rule_memory_action.rb
@@ -150,7 +151,6 @@ files:
150
151
  - lib/nanoc/base/views/mutable_layout_view.rb
151
152
  - lib/nanoc/base/views/post_compile_item_collection_view.rb
152
153
  - lib/nanoc/base/views/post_compile_item_view.rb
153
- - lib/nanoc/base/views/site_view.rb
154
154
  - lib/nanoc/base/views/view.rb
155
155
  - lib/nanoc/base/views/view_context.rb
156
156
  - lib/nanoc/cli.rb
@@ -176,7 +176,6 @@ files:
176
176
  - lib/nanoc/cli/stream_cleaners/utf8.rb
177
177
  - lib/nanoc/data_sources.rb
178
178
  - lib/nanoc/data_sources/filesystem.rb
179
- - lib/nanoc/data_sources/filesystem_unified.rb
180
179
  - lib/nanoc/extra.rb
181
180
  - lib/nanoc/extra/checking.rb
182
181
  - lib/nanoc/extra/checking/check.rb
@@ -187,6 +186,7 @@ files:
187
186
  - lib/nanoc/extra/checking/checks/internal_links.rb
188
187
  - lib/nanoc/extra/checking/checks/mixed_content.rb
189
188
  - lib/nanoc/extra/checking/checks/stale.rb
189
+ - lib/nanoc/extra/checking/checks/w3c_validator.rb
190
190
  - lib/nanoc/extra/checking/dsl.rb
191
191
  - lib/nanoc/extra/checking/issue.rb
192
192
  - lib/nanoc/extra/checking/runner.rb
@@ -235,6 +235,7 @@ files:
235
235
  - lib/nanoc/helpers/blogging.rb
236
236
  - lib/nanoc/helpers/breadcrumbs.rb
237
237
  - lib/nanoc/helpers/capturing.rb
238
+ - lib/nanoc/helpers/child_parent.rb
238
239
  - lib/nanoc/helpers/filtering.rb
239
240
  - lib/nanoc/helpers/html_escape.rb
240
241
  - lib/nanoc/helpers/link_to.rb
@@ -251,6 +252,7 @@ files:
251
252
  - lib/nanoc/rule_dsl/rule_memory_calculator.rb
252
253
  - lib/nanoc/rule_dsl/rules_collection.rb
253
254
  - lib/nanoc/rule_dsl/rules_loader.rb
255
+ - lib/nanoc/spec.rb
254
256
  - lib/nanoc/version.rb
255
257
  - nanoc.gemspec
256
258
  - tasks/doc.rake
@@ -290,7 +292,6 @@ files:
290
292
  - test/cli/test_error_handler.rb
291
293
  - test/cli/test_logger.rb
292
294
  - test/data_sources/test_filesystem.rb
293
- - test/data_sources/test_filesystem_unified.rb
294
295
  - test/extra/checking/checks/test_css.rb
295
296
  - test/extra/checking/checks/test_external_links.rb
296
297
  - test/extra/checking/checks/test_html.rb
@@ -341,14 +342,8 @@ files:
341
342
  - test/fixtures/vcr_cassettes/html_run_ok.yml
342
343
  - test/helper.rb
343
344
  - test/helpers/test_blogging.rb
344
- - test/helpers/test_breadcrumbs.rb
345
345
  - test/helpers/test_capturing.rb
346
- - test/helpers/test_filtering.rb
347
- - test/helpers/test_html_escape.rb
348
346
  - test/helpers/test_link_to.rb
349
- - test/helpers/test_rendering.rb
350
- - test/helpers/test_tagging.rb
351
- - test/helpers/test_text.rb
352
347
  - test/helpers/test_xml_sitemap.rb
353
348
  - test/rule_dsl/test_action_provider.rb
354
349
  - test/rule_dsl/test_compiler_dsl.rb
@@ -372,9 +367,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
372
367
  version: 2.1.0
373
368
  required_rubygems_version: !ruby/object:Gem::Requirement
374
369
  requirements:
375
- - - ">="
370
+ - - ">"
376
371
  - !ruby/object:Gem::Version
377
- version: '0'
372
+ version: 1.3.1
378
373
  requirements: []
379
374
  rubyforge_project:
380
375
  rubygems_version: 2.6.2
@@ -1,14 +0,0 @@
1
- module Nanoc
2
- class SiteView < ::Nanoc::View
3
- # @api private
4
- def initialize(site, context)
5
- super(context)
6
- @site = site
7
- end
8
-
9
- # @api private
10
- def unwrap
11
- @site
12
- end
13
- end
14
- end
@@ -1,101 +0,0 @@
1
- module Nanoc::DataSources
2
- # The filesystem_unified data source stores its items and layouts in nested
3
- # directories. Items and layouts are represented by one or two files; if it
4
- # is represented using one file, the metadata can be contained in this file.
5
- #
6
- # The default root directory for items is the `content` directory; for
7
- # layouts, this is the `layouts` directory. This can be overridden
8
- # in the data source configuration:
9
- #
10
- # data_sources:
11
- # - type: filesystem_unified
12
- # content_dir: items
13
- # layouts_dir: layouts
14
- #
15
- # The metadata for items and layouts can be stored in a separate file with
16
- # the same base name but with the `.yaml` extension. If such a file is
17
- # found, metadata is read from that file. Alternatively, the content file
18
- # itself can start with a metadata section: it can be stored at the top of
19
- # the file, between `---` (three dashes) separators. For example:
20
- #
21
- # ---
22
- # title: "Moo!"
23
- # ---
24
- # h1. Hello!
25
- #
26
- # The metadata section can be omitted. If the file does not start with
27
- # three or five dashes, the entire file will be considered as content.
28
- #
29
- # The identifier of items and layouts is determined as follows. A file with
30
- # an `index.*` filename, such as `index.txt`, will have the filesystem path
31
- # with the `index.*` part stripped as a identifier. For example:
32
- #
33
- # foo/bar/index.html → /foo/bar/
34
- #
35
- # In other cases, the identifier is calculated by stripping the extension.
36
- # If the `allow_periods_in_identifiers` attribute in the configuration is
37
- # true, only the last extension will be stripped if the file has multiple
38
- # extensions; if it is false or unset, all extensions will be stripped.
39
- # For example:
40
- #
41
- # (`allow_periods_in_identifiers` set to true)
42
- # foo.entry.html → /foo.entry/
43
- #
44
- # (`allow_periods_in_identifiers` set to false)
45
- # foo.html.erb → /foo/
46
- #
47
- # Note that each item must have an unique identifier. Nanoc will display an
48
- # error if two items with the same identifier are found.
49
- #
50
- # Some more examples:
51
- #
52
- # content/index.html → /
53
- # content/foo.html → /foo/
54
- # content/foo/index.html → /foo/
55
- # content/foo/bar.html → /foo/bar/
56
- # content/foo/bar.baz.html → /foo/bar/ OR /foo/bar.baz/
57
- # content/foo/bar/index.html → /foo/bar/
58
- # content/foo.bar/index.html → /foo.bar/
59
- #
60
- # The file extension does not determine the filters to run on items; the
61
- # Rules file is used to specify processing instructors for each item.
62
- #
63
- # It is possible to set an explicit encoding that should be used when reading
64
- # files. In the data source configuration, set `encoding` to an encoding
65
- # understood by Ruby’s `Encoding`. If no encoding is set in the configuration,
66
- # one will be inferred from the environment.
67
- #
68
- # @api private
69
- class FilesystemUnified < Nanoc::DataSource
70
- include Nanoc::DataSources::Filesystem
71
-
72
- private
73
-
74
- # See {Nanoc::DataSources::Filesystem#filename_for}.
75
- def filename_for(base_filename, ext)
76
- if ext.nil?
77
- nil
78
- elsif ext.empty?
79
- base_filename
80
- else
81
- base_filename + '.' + ext
82
- end
83
- end
84
-
85
- # Returns the identifier derived from the given filename, first stripping
86
- # the given directory name off the filename.
87
- def identifier_for_filename(filename)
88
- if config[:identifier_type] == 'full'
89
- return Nanoc::Identifier.new(filename)
90
- end
91
-
92
- regex =
93
- if filename =~ /(^|\/)index(\.[^\/]+)?$/
94
- @config && @config[:allow_periods_in_identifiers] ? /\/?(index)?(\.[^\/\.]+)?$/ : /\/?index(\.[^\/]+)?$/
95
- else
96
- @config && @config[:allow_periods_in_identifiers] ? /\.[^\/\.]+$/ : /\.[^\/]+$/
97
- end
98
- Nanoc::Identifier.new(filename.sub(regex, ''), type: :legacy)
99
- end
100
- end
101
- end
@@ -1,559 +0,0 @@
1
- class Nanoc::DataSources::FilesystemUnifiedTest < Nanoc::TestCase
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::FilesystemUnified.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', 'The 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
68
- end
69
-
70
- def test_load_objects_with_same_extensions
71
- # Create data source
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") }
90
-
91
- # Check
92
- actual_out = data_source.send(:load_objects, 'foo', 'The Foo', klass)
93
- assert_equal 2, actual_out.size
94
- end
95
-
96
- def test_load_binary_objects
97
- # Create data source
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', 'item', Nanoc::Int::Item)
106
-
107
- # Check
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', 'item', 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', 'The 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', 'The 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', 'The 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
558
- end
559
- end