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,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