nanoc 3.2.4 → 3.3.0

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 (230) hide show
  1. data/.gemtest +0 -0
  2. data/ChangeLog +3 -0
  3. data/Gemfile +32 -0
  4. data/LICENSE +19 -0
  5. data/NEWS.md +470 -0
  6. data/README.md +114 -0
  7. data/Rakefile +14 -0
  8. data/bin/nanoc +7 -27
  9. data/bin/nanoc3 +3 -0
  10. data/doc/yardoc_templates/default/layout/html/footer.erb +10 -0
  11. data/lib/nanoc.rb +41 -0
  12. data/lib/nanoc/base.rb +49 -0
  13. data/lib/nanoc/base/compilation/checksum_store.rb +57 -0
  14. data/lib/nanoc/base/compilation/compiled_content_cache.rb +62 -0
  15. data/lib/nanoc/base/compilation/compiler.rb +458 -0
  16. data/lib/nanoc/base/compilation/compiler_dsl.rb +214 -0
  17. data/lib/nanoc/base/compilation/dependency_tracker.rb +200 -0
  18. data/lib/nanoc/base/compilation/filter.rb +165 -0
  19. data/lib/nanoc/base/compilation/item_rep_proxy.rb +103 -0
  20. data/lib/nanoc/base/compilation/item_rep_recorder_proxy.rb +102 -0
  21. data/lib/nanoc/base/compilation/outdatedness_checker.rb +223 -0
  22. data/lib/nanoc/base/compilation/outdatedness_reasons.rb +46 -0
  23. data/lib/nanoc/base/compilation/rule.rb +73 -0
  24. data/lib/nanoc/base/compilation/rule_context.rb +84 -0
  25. data/lib/nanoc/base/compilation/rule_memory_calculator.rb +40 -0
  26. data/lib/nanoc/base/compilation/rule_memory_store.rb +53 -0
  27. data/lib/nanoc/base/compilation/rules_collection.rb +243 -0
  28. data/lib/nanoc/base/context.rb +47 -0
  29. data/lib/nanoc/base/core_ext.rb +6 -0
  30. data/lib/nanoc/base/core_ext/array.rb +62 -0
  31. data/lib/nanoc/base/core_ext/hash.rb +63 -0
  32. data/lib/nanoc/base/core_ext/pathname.rb +26 -0
  33. data/lib/nanoc/base/core_ext/string.rb +46 -0
  34. data/lib/nanoc/base/directed_graph.rb +275 -0
  35. data/lib/nanoc/base/errors.rb +211 -0
  36. data/lib/nanoc/base/memoization.rb +67 -0
  37. data/lib/nanoc/base/notification_center.rb +84 -0
  38. data/lib/nanoc/base/ordered_hash.rb +200 -0
  39. data/lib/nanoc/base/plugin_registry.rb +181 -0
  40. data/lib/nanoc/base/result_data/item_rep.rb +492 -0
  41. data/lib/nanoc/base/source_data/code_snippet.rb +58 -0
  42. data/lib/nanoc/base/source_data/configuration.rb +24 -0
  43. data/lib/nanoc/base/source_data/data_source.rb +234 -0
  44. data/lib/nanoc/base/source_data/item.rb +301 -0
  45. data/lib/nanoc/base/source_data/layout.rb +130 -0
  46. data/lib/nanoc/base/source_data/site.rb +361 -0
  47. data/lib/nanoc/base/store.rb +135 -0
  48. data/lib/nanoc/cli.rb +137 -0
  49. data/lib/nanoc/cli/command_runner.rb +104 -0
  50. data/lib/nanoc/cli/commands/autocompile.rb +58 -0
  51. data/lib/nanoc/cli/commands/compile.rb +297 -0
  52. data/lib/nanoc/cli/commands/create_item.rb +60 -0
  53. data/lib/nanoc/cli/commands/create_layout.rb +73 -0
  54. data/lib/nanoc/cli/commands/create_site.rb +411 -0
  55. data/lib/nanoc/cli/commands/debug.rb +117 -0
  56. data/lib/nanoc/cli/commands/deploy.rb +79 -0
  57. data/lib/nanoc/cli/commands/info.rb +98 -0
  58. data/lib/nanoc/cli/commands/nanoc.rb +38 -0
  59. data/lib/nanoc/cli/commands/prune.rb +50 -0
  60. data/lib/nanoc/cli/commands/update.rb +70 -0
  61. data/lib/nanoc/cli/commands/view.rb +82 -0
  62. data/lib/nanoc/cli/commands/watch.rb +124 -0
  63. data/lib/nanoc/cli/error_handler.rb +199 -0
  64. data/lib/nanoc/cli/logger.rb +92 -0
  65. data/lib/nanoc/data_sources.rb +29 -0
  66. data/lib/nanoc/data_sources/deprecated/delicious.rb +42 -0
  67. data/lib/nanoc/data_sources/deprecated/last_fm.rb +87 -0
  68. data/lib/nanoc/data_sources/deprecated/twitter.rb +38 -0
  69. data/lib/nanoc/data_sources/filesystem.rb +299 -0
  70. data/lib/nanoc/data_sources/filesystem_unified.rb +121 -0
  71. data/lib/nanoc/data_sources/filesystem_verbose.rb +91 -0
  72. data/lib/nanoc/extra.rb +24 -0
  73. data/lib/nanoc/extra/auto_compiler.rb +103 -0
  74. data/lib/nanoc/extra/chick.rb +125 -0
  75. data/lib/nanoc/extra/core_ext.rb +6 -0
  76. data/lib/nanoc/extra/core_ext/enumerable.rb +33 -0
  77. data/lib/nanoc/extra/core_ext/pathname.rb +30 -0
  78. data/lib/nanoc/extra/core_ext/time.rb +19 -0
  79. data/lib/nanoc/extra/deployer.rb +47 -0
  80. data/lib/nanoc/extra/deployers.rb +15 -0
  81. data/lib/nanoc/extra/deployers/fog.rb +98 -0
  82. data/lib/nanoc/extra/deployers/rsync.rb +70 -0
  83. data/lib/nanoc/extra/file_proxy.rb +40 -0
  84. data/lib/nanoc/extra/pruner.rb +86 -0
  85. data/lib/nanoc/extra/validators.rb +12 -0
  86. data/lib/nanoc/extra/validators/links.rb +268 -0
  87. data/lib/nanoc/extra/validators/w3c.rb +95 -0
  88. data/lib/nanoc/extra/vcs.rb +66 -0
  89. data/lib/nanoc/extra/vcses.rb +17 -0
  90. data/lib/nanoc/extra/vcses/bazaar.rb +25 -0
  91. data/lib/nanoc/extra/vcses/dummy.rb +24 -0
  92. data/lib/nanoc/extra/vcses/git.rb +25 -0
  93. data/lib/nanoc/extra/vcses/mercurial.rb +25 -0
  94. data/lib/nanoc/extra/vcses/subversion.rb +25 -0
  95. data/lib/nanoc/filters.rb +59 -0
  96. data/lib/nanoc/filters/asciidoc.rb +38 -0
  97. data/lib/nanoc/filters/bluecloth.rb +19 -0
  98. data/lib/nanoc/filters/coderay.rb +21 -0
  99. data/lib/nanoc/filters/coffeescript.rb +20 -0
  100. data/lib/nanoc/filters/colorize_syntax.rb +298 -0
  101. data/lib/nanoc/filters/erb.rb +38 -0
  102. data/lib/nanoc/filters/erubis.rb +34 -0
  103. data/lib/nanoc/filters/haml.rb +27 -0
  104. data/lib/nanoc/filters/kramdown.rb +20 -0
  105. data/lib/nanoc/filters/less.rb +53 -0
  106. data/lib/nanoc/filters/markaby.rb +20 -0
  107. data/lib/nanoc/filters/maruku.rb +20 -0
  108. data/lib/nanoc/filters/mustache.rb +24 -0
  109. data/lib/nanoc/filters/rainpress.rb +19 -0
  110. data/lib/nanoc/filters/rdiscount.rb +22 -0
  111. data/lib/nanoc/filters/rdoc.rb +33 -0
  112. data/lib/nanoc/filters/redcarpet.rb +62 -0
  113. data/lib/nanoc/filters/redcloth.rb +47 -0
  114. data/lib/nanoc/filters/relativize_paths.rb +94 -0
  115. data/lib/nanoc/filters/rubypants.rb +20 -0
  116. data/lib/nanoc/filters/sass.rb +74 -0
  117. data/lib/nanoc/filters/slim.rb +25 -0
  118. data/lib/nanoc/filters/typogruby.rb +23 -0
  119. data/lib/nanoc/filters/uglify_js.rb +42 -0
  120. data/lib/nanoc/filters/xsl.rb +46 -0
  121. data/lib/nanoc/filters/yui_compressor.rb +23 -0
  122. data/lib/nanoc/helpers.rb +16 -0
  123. data/lib/nanoc/helpers/blogging.rb +319 -0
  124. data/lib/nanoc/helpers/breadcrumbs.rb +40 -0
  125. data/lib/nanoc/helpers/capturing.rb +138 -0
  126. data/lib/nanoc/helpers/filtering.rb +50 -0
  127. data/lib/nanoc/helpers/html_escape.rb +55 -0
  128. data/lib/nanoc/helpers/link_to.rb +151 -0
  129. data/lib/nanoc/helpers/rendering.rb +140 -0
  130. data/lib/nanoc/helpers/tagging.rb +71 -0
  131. data/lib/nanoc/helpers/text.rb +44 -0
  132. data/lib/nanoc/helpers/xml_sitemap.rb +76 -0
  133. data/lib/nanoc/tasks.rb +10 -0
  134. data/lib/nanoc/tasks/clean.rake +16 -0
  135. data/lib/nanoc/tasks/clean.rb +29 -0
  136. data/lib/nanoc/tasks/deploy/rsync.rake +16 -0
  137. data/lib/nanoc/tasks/validate.rake +92 -0
  138. data/nanoc.gemspec +49 -0
  139. data/tasks/doc.rake +16 -0
  140. data/tasks/test.rake +46 -0
  141. data/test/base/core_ext/array_spec.rb +73 -0
  142. data/test/base/core_ext/hash_spec.rb +98 -0
  143. data/test/base/core_ext/pathname_spec.rb +27 -0
  144. data/test/base/core_ext/string_spec.rb +37 -0
  145. data/test/base/test_checksum_store.rb +35 -0
  146. data/test/base/test_code_snippet.rb +31 -0
  147. data/test/base/test_compiler.rb +403 -0
  148. data/test/base/test_compiler_dsl.rb +161 -0
  149. data/test/base/test_context.rb +31 -0
  150. data/test/base/test_data_source.rb +46 -0
  151. data/test/base/test_dependency_tracker.rb +262 -0
  152. data/test/base/test_directed_graph.rb +288 -0
  153. data/test/base/test_filter.rb +83 -0
  154. data/test/base/test_item.rb +179 -0
  155. data/test/base/test_item_rep.rb +579 -0
  156. data/test/base/test_layout.rb +59 -0
  157. data/test/base/test_memoization.rb +90 -0
  158. data/test/base/test_notification_center.rb +34 -0
  159. data/test/base/test_outdatedness_checker.rb +394 -0
  160. data/test/base/test_plugin.rb +30 -0
  161. data/test/base/test_rule.rb +19 -0
  162. data/test/base/test_rule_context.rb +65 -0
  163. data/test/base/test_site.rb +190 -0
  164. data/test/cli/commands/test_compile.rb +33 -0
  165. data/test/cli/commands/test_create_item.rb +14 -0
  166. data/test/cli/commands/test_create_layout.rb +28 -0
  167. data/test/cli/commands/test_create_site.rb +24 -0
  168. data/test/cli/commands/test_deploy.rb +74 -0
  169. data/test/cli/commands/test_help.rb +12 -0
  170. data/test/cli/commands/test_info.rb +11 -0
  171. data/test/cli/commands/test_prune.rb +98 -0
  172. data/test/cli/commands/test_update.rb +10 -0
  173. data/test/cli/test_cli.rb +102 -0
  174. data/test/cli/test_error_handler.rb +29 -0
  175. data/test/cli/test_logger.rb +10 -0
  176. data/test/data_sources/test_filesystem.rb +433 -0
  177. data/test/data_sources/test_filesystem_unified.rb +536 -0
  178. data/test/data_sources/test_filesystem_verbose.rb +357 -0
  179. data/test/extra/core_ext/test_enumerable.rb +30 -0
  180. data/test/extra/core_ext/test_pathname.rb +17 -0
  181. data/test/extra/core_ext/test_time.rb +15 -0
  182. data/test/extra/deployers/test_fog.rb +67 -0
  183. data/test/extra/deployers/test_rsync.rb +100 -0
  184. data/test/extra/test_auto_compiler.rb +417 -0
  185. data/test/extra/test_file_proxy.rb +19 -0
  186. data/test/extra/test_vcs.rb +22 -0
  187. data/test/extra/validators/test_links.rb +62 -0
  188. data/test/extra/validators/test_w3c.rb +47 -0
  189. data/test/filters/test_asciidoc.rb +22 -0
  190. data/test/filters/test_bluecloth.rb +18 -0
  191. data/test/filters/test_coderay.rb +44 -0
  192. data/test/filters/test_coffeescript.rb +18 -0
  193. data/test/filters/test_colorize_syntax.rb +379 -0
  194. data/test/filters/test_erb.rb +105 -0
  195. data/test/filters/test_erubis.rb +78 -0
  196. data/test/filters/test_haml.rb +96 -0
  197. data/test/filters/test_kramdown.rb +18 -0
  198. data/test/filters/test_less.rb +113 -0
  199. data/test/filters/test_markaby.rb +24 -0
  200. data/test/filters/test_maruku.rb +18 -0
  201. data/test/filters/test_mustache.rb +25 -0
  202. data/test/filters/test_rainpress.rb +29 -0
  203. data/test/filters/test_rdiscount.rb +31 -0
  204. data/test/filters/test_rdoc.rb +18 -0
  205. data/test/filters/test_redcarpet.rb +73 -0
  206. data/test/filters/test_redcloth.rb +33 -0
  207. data/test/filters/test_relativize_paths.rb +533 -0
  208. data/test/filters/test_rubypants.rb +18 -0
  209. data/test/filters/test_sass.rb +229 -0
  210. data/test/filters/test_slim.rb +35 -0
  211. data/test/filters/test_typogruby.rb +21 -0
  212. data/test/filters/test_uglify_js.rb +30 -0
  213. data/test/filters/test_xsl.rb +105 -0
  214. data/test/filters/test_yui_compressor.rb +44 -0
  215. data/test/gem_loader.rb +11 -0
  216. data/test/helper.rb +207 -0
  217. data/test/helpers/test_blogging.rb +754 -0
  218. data/test/helpers/test_breadcrumbs.rb +81 -0
  219. data/test/helpers/test_capturing.rb +41 -0
  220. data/test/helpers/test_filtering.rb +106 -0
  221. data/test/helpers/test_html_escape.rb +32 -0
  222. data/test/helpers/test_link_to.rb +249 -0
  223. data/test/helpers/test_rendering.rb +89 -0
  224. data/test/helpers/test_tagging.rb +87 -0
  225. data/test/helpers/test_text.rb +24 -0
  226. data/test/helpers/test_xml_sitemap.rb +103 -0
  227. data/test/tasks/test_clean.rb +67 -0
  228. metadata +327 -15
  229. data/bin/nanoc-select +0 -86
  230. data/lib/nanoc-select.rb +0 -11
@@ -0,0 +1,579 @@
1
+ # encoding: utf-8
2
+
3
+ class Nanoc::ItemRepTest < MiniTest::Unit::TestCase
4
+
5
+ include Nanoc::TestHelpers
6
+
7
+ def test_created_modified_compiled
8
+ # TODO implement
9
+ end
10
+
11
+ def test_compiled_content_with_only_last_available
12
+ # Create rep
13
+ item = Nanoc::Item.new(
14
+ 'blah blah blah', {}, '/',
15
+ :binary => false, :mtime => Time.now-500
16
+ )
17
+ rep = Nanoc::ItemRep.new(item, nil)
18
+ rep.instance_eval { @content = { :last => 'last content' } }
19
+ rep.expects(:compiled?).returns(true)
20
+
21
+ # Check
22
+ assert_equal 'last content', rep.compiled_content
23
+ end
24
+
25
+ def test_compiled_content_with_pre_and_last_available
26
+ # Create rep
27
+ item = Nanoc::Item.new(
28
+ 'blah blah blah', {}, '/',
29
+ :binary => false, :mtime => Time.now-500
30
+ )
31
+ rep = Nanoc::ItemRep.new(item, nil)
32
+ rep.instance_eval { @content = { :pre => 'pre content', :last => 'last content' } }
33
+ rep.expects(:compiled?).returns(true)
34
+
35
+ # Check
36
+ assert_equal 'pre content', rep.compiled_content
37
+ end
38
+
39
+ def test_compiled_content_with_custom_snapshot
40
+ # Create rep
41
+ item = Nanoc::Item.new(
42
+ 'blah blah blah', {}, '/',
43
+ :binary => false, :mtime => Time.now-500
44
+ )
45
+ rep = Nanoc::ItemRep.new(item, nil)
46
+ rep.instance_eval { @content = { :pre => 'pre content', :last => 'last content' } }
47
+ rep.expects(:compiled?).returns(true)
48
+
49
+ # Check
50
+ assert_equal 'last content', rep.compiled_content(:snapshot => :last)
51
+ end
52
+
53
+ def test_compiled_content_with_invalid_snapshot
54
+ # Create rep
55
+ item = Nanoc::Item.new(
56
+ 'blah blah blah', {}, '/',
57
+ :binary => false, :mtime => Time.now-500
58
+ )
59
+ rep = Nanoc::ItemRep.new(item, nil)
60
+ rep.instance_eval { @content = { :pre => 'pre content', :last => 'last content' } }
61
+
62
+ # Check
63
+ assert_raises Nanoc::Errors::NoSuchSnapshot do
64
+ rep.compiled_content(:snapshot => :klsjflkasdfl)
65
+ end
66
+ end
67
+
68
+ def test_compiled_content_with_uncompiled_content
69
+ # Create rep
70
+ item = Nanoc::Item.new(
71
+ "blah blah", {}, '/',
72
+ :binary => false
73
+ )
74
+ rep = Nanoc::ItemRep.new(item, nil)
75
+ rep.expects(:compiled?).returns(false)
76
+
77
+ # Check
78
+ assert_raises(Nanoc::Errors::UnmetDependency) do
79
+ rep.compiled_content
80
+ end
81
+ end
82
+
83
+ def test_filter
84
+ # Mock site
85
+ site = MiniTest::Mock.new
86
+ site.expect(:items, [])
87
+ site.expect(:config, [])
88
+ site.expect(:layouts, [])
89
+
90
+ # Mock item
91
+ item = Nanoc::Item.new(
92
+ %[<%= '<%= "blah" %' + '>' %>], {}, '/',
93
+ :binary => false
94
+ )
95
+
96
+ # Create item rep
97
+ item_rep = Nanoc::ItemRep.new(item, :foo)
98
+ item_rep.instance_eval do
99
+ @content[:raw] = item.raw_content
100
+ @content[:last] = @content[:raw]
101
+ end
102
+
103
+ # Filter once
104
+ item_rep.assigns = {}
105
+ item_rep.filter(:erb)
106
+ assert_equal(%[<%= "blah" %>], item_rep.instance_eval { @content[:last] })
107
+
108
+ # Filter twice
109
+ item_rep.assigns = {}
110
+ item_rep.filter(:erb)
111
+ assert_equal(%[blah], item_rep.instance_eval { @content[:last] })
112
+ end
113
+
114
+ def test_layout
115
+ # Mock layout
116
+ layout = Nanoc::Layout.new(%[<%= "blah" %>], {}, '/somelayout/')
117
+
118
+ # Mock item
119
+ item = Nanoc::Item.new(
120
+ "blah blah", {}, '/',
121
+ :binary => false
122
+ )
123
+
124
+ # Create item rep
125
+ item_rep = Nanoc::ItemRep.new(item, :foo)
126
+ item_rep.instance_eval do
127
+ @content[:raw] = item.raw_content
128
+ @content[:last] = @content[:raw]
129
+ end
130
+
131
+ # Layout
132
+ item_rep.assigns = {}
133
+ item_rep.layout(layout, :erb, {})
134
+ assert_equal(%[blah], item_rep.instance_eval { @content[:last] })
135
+ end
136
+
137
+ def test_snapshot
138
+ # Mock site
139
+ site = MiniTest::Mock.new
140
+ site.expect(:items, [])
141
+ site.expect(:config, [])
142
+ site.expect(:layouts, [])
143
+
144
+ # Mock item
145
+ item = Nanoc::Item.new(
146
+ %[<%= '<%= "blah" %' + '>' %>], {}, '/foobar/',
147
+ :binary => false
148
+ )
149
+
150
+ # Create item rep
151
+ item_rep = Nanoc::ItemRep.new(item, :foo)
152
+ item_rep.instance_eval do
153
+ @content[:raw] = item.raw_content
154
+ @content[:last] = @content[:raw]
155
+ end
156
+
157
+ # Filter while taking snapshots
158
+ item_rep.assigns = {}
159
+ item_rep.snapshot(:foo)
160
+ item_rep.filter(:erb)
161
+ item_rep.snapshot(:bar)
162
+ item_rep.filter(:erb)
163
+ item_rep.snapshot(:qux)
164
+
165
+ # Check snapshots
166
+ assert_equal(%[<%= '<%= "blah" %' + '>' %>], item_rep.instance_eval { @content[:foo] })
167
+ assert_equal(%[<%= "blah" %>], item_rep.instance_eval { @content[:bar] })
168
+ assert_equal(%[blah], item_rep.instance_eval { @content[:qux] })
169
+ end
170
+
171
+ def test_snapshot_should_be_written
172
+ # Mock item
173
+ item = Nanoc::Item.new(
174
+ "blah blah", {}, '/',
175
+ :binary => false
176
+ )
177
+
178
+ # Create rep
179
+ item_rep = Nanoc::ItemRep.new(item, :foo)
180
+ item_rep.instance_eval { @content[:last] = 'Lorem ipsum, etc.' }
181
+ item_rep.raw_paths = { :moo => 'foo-moo.txt' }
182
+
183
+ # Test non-final
184
+ refute File.file?(item_rep.raw_path(:snapshot => :moo))
185
+ item_rep.snapshot(:moo, :final => false)
186
+ refute File.file?(item_rep.raw_path(:snapshot => :moo))
187
+
188
+ # Test final 1
189
+ item_rep.snapshot(:moo, :final => true)
190
+ assert File.file?(item_rep.raw_path(:snapshot => :moo))
191
+ assert_equal 'Lorem ipsum, etc.', File.read(item_rep.raw_path(:snapshot => :moo))
192
+ FileUtils.rm_f(item_rep.raw_path(:snapshot => :moo))
193
+
194
+ # Test final 2
195
+ item_rep.snapshot(:moo)
196
+ assert File.file?(item_rep.raw_path(:snapshot => :moo))
197
+ assert_equal 'Lorem ipsum, etc.', File.read(item_rep.raw_path(:snapshot => :moo))
198
+ end
199
+
200
+ def test_write_should_not_touch_identical_textual_files
201
+ # Mock item
202
+ item = Nanoc::Item.new(
203
+ "blah blah", {}, '/',
204
+ :binary => false
205
+ )
206
+
207
+ # Create rep
208
+ item_rep = Nanoc::ItemRep.new(item, :foo)
209
+ def item_rep.generate_diff ; end
210
+ item_rep.instance_eval { @content[:last] = 'Lorem ipsum, etc.' }
211
+ item_rep.raw_path = 'foo/bar/baz/quux.txt'
212
+
213
+ # Write once
214
+ item_rep.write
215
+ a_long_time_ago = Time.now-1_000_000
216
+ File.utime(a_long_time_ago, a_long_time_ago, item_rep.raw_path)
217
+
218
+ # Write again
219
+ assert_equal a_long_time_ago.to_s, File.mtime(item_rep.raw_path).to_s
220
+ item_rep.write
221
+ assert_equal a_long_time_ago.to_s, File.mtime(item_rep.raw_path).to_s
222
+ end
223
+
224
+ def test_write_should_not_touch_identical_binary_files
225
+ # Create temporary source file
226
+ File.open('blahblah', 'w') { |io| io.write("Blah blah…") }
227
+ full_file_path = File.expand_path('blahblah')
228
+
229
+ # Mock item
230
+ item = Nanoc::Item.new(
231
+ full_file_path, {}, '/',
232
+ :binary => true
233
+ )
234
+
235
+ # Create rep
236
+ item_rep = Nanoc::ItemRep.new(item, :foo)
237
+ item_rep.raw_path = 'foo/bar/baz/quux'
238
+
239
+ # Write once
240
+ item_rep.write
241
+ a_long_time_ago = Time.now-1_000_000
242
+ File.utime(a_long_time_ago, a_long_time_ago, item_rep.raw_path)
243
+
244
+ # Write again
245
+ assert_equal a_long_time_ago.to_s, File.mtime(item_rep.raw_path).to_s
246
+ item_rep.write
247
+ assert_equal a_long_time_ago.to_s, File.mtime(item_rep.raw_path).to_s
248
+ end
249
+
250
+ def test_write
251
+ # Mock item
252
+ item = Nanoc::Item.new(
253
+ "blah blah", {}, '/',
254
+ :binary => false
255
+ )
256
+
257
+ # Create rep
258
+ item_rep = Nanoc::ItemRep.new(item, :foo)
259
+ item_rep.instance_eval { @content[:last] = 'Lorem ipsum, etc.' }
260
+ item_rep.raw_path = 'foo/bar/baz/quux.txt'
261
+
262
+ # Write
263
+ item_rep.write
264
+
265
+ # Check
266
+ assert(File.file?('foo/bar/baz/quux.txt'))
267
+ assert_equal('Lorem ipsum, etc.', File.read('foo/bar/baz/quux.txt'))
268
+ end
269
+
270
+ def test_filter_text_to_binary
271
+ # Mock item
272
+ item = Nanoc::Item.new(
273
+ "blah blah", {}, '/',
274
+ :binary => false
275
+ )
276
+
277
+ # Create rep
278
+ rep = Nanoc::ItemRep.new(item, :foo)
279
+ def rep.assigns ; {} ; end
280
+
281
+ # Create fake filter
282
+ def rep.filter_named(name)
283
+ @filter ||= Class.new(::Nanoc::Filter) do
284
+ type :text => :binary
285
+ def run(content, params={})
286
+ File.open(output_filename, 'w') { |io| io.write(content) }
287
+ end
288
+ end
289
+ end
290
+
291
+ # Run
292
+ rep.filter(:foo)
293
+
294
+ # Check
295
+ assert rep.binary?
296
+ end
297
+
298
+ def test_filter_with_textual_rep_and_binary_filter
299
+ # Mock item
300
+ item = Nanoc::Item.new(
301
+ "blah blah", {}, '/',
302
+ :binary => false
303
+ )
304
+
305
+ # Create rep
306
+ rep = Nanoc::ItemRep.new(item, :foo)
307
+ def rep.assigns ; {} ; end
308
+
309
+ # Create fake filter
310
+ def rep.filter_named(name)
311
+ @filter ||= Class.new(::Nanoc::Filter) do
312
+ type :binary
313
+ def run(content, params={})
314
+ File.open(output_filename, 'w') { |io| io.write(content) }
315
+ end
316
+ end
317
+ end
318
+
319
+ # Run
320
+ assert_raises ::Nanoc::Errors::CannotUseBinaryFilter do
321
+ rep.filter(:foo)
322
+ end
323
+ end
324
+
325
+ def test_using_textual_filters_on_binary_reps_raises
326
+ item = create_binary_item
327
+ site = mock_and_stub(:items => [item],
328
+ :layouts => [],
329
+ :config => []
330
+ )
331
+ item.stubs(:site).returns(site)
332
+ rep = create_rep_for(item, :foo)
333
+ create_textual_filter
334
+
335
+ assert rep.binary?
336
+ assert_raises(Nanoc::Errors::CannotUseTextualFilter) { rep.filter(:text_filter) }
337
+ end
338
+
339
+ def test_writing_binary_reps_uses_content_in_last_filename
340
+ require 'tempfile'
341
+
342
+ in_filename = 'nanoc-in'
343
+ out_filename = 'nanoc-out'
344
+ file_content = 'Some content for this test'
345
+ File.open(in_filename, 'w') { |io| io.write(file_content) }
346
+
347
+ item = create_binary_item
348
+ rep = create_rep_for(item, :foo)
349
+ rep.temporary_filenames[:last] = in_filename
350
+ rep.raw_paths[:last] = out_filename
351
+
352
+ rep.write
353
+
354
+ assert(File.exist?(out_filename))
355
+ assert_equal(file_content, File.read(out_filename))
356
+ end
357
+
358
+ def test_converted_binary_rep_can_be_layed_out
359
+ # Mock layout
360
+ layout = Nanoc::Layout.new(%[<%= "blah" %> <%= yield %>], {}, '/somelayout/')
361
+
362
+ # Create item and item rep
363
+ item = create_binary_item
364
+ rep = create_rep_for(item, :foo)
365
+ rep.assigns = { :content => 'meh' }
366
+
367
+ # Create filter
368
+ Class.new(::Nanoc::Filter) do
369
+ type :binary => :text
370
+ identifier :binary_to_text
371
+ def run(content, params={})
372
+ content + ' textified'
373
+ end
374
+ end
375
+
376
+ # Run and check
377
+ rep.filter(:binary_to_text)
378
+ rep.layout(layout, :erb, {})
379
+ assert_equal('blah meh', rep.instance_eval { @content[:last] })
380
+ end
381
+
382
+ def test_converted_binary_rep_can_be_filtered_with_textual_filters
383
+ item = create_binary_item
384
+ site = mock_and_stub(:items => [item],
385
+ :layouts => [],
386
+ :config => []
387
+ )
388
+ item.stubs(:site).returns(site)
389
+ rep = create_rep_for(item, :foo)
390
+ rep.assigns = {}
391
+ create_textual_filter
392
+
393
+ assert rep.binary?
394
+
395
+ def rep.filter_named(name)
396
+ Class.new(::Nanoc::Filter) do
397
+ type :binary => :text
398
+ def run(content, params={})
399
+ "Some textual content"
400
+ end
401
+ end
402
+ end
403
+ rep.filter(:binary_to_text)
404
+ assert !rep.binary?
405
+
406
+ def rep.filter_named(name)
407
+ Class.new(::Nanoc::Filter) do
408
+ type :text
409
+ def run(content, params={})
410
+ "Some textual content"
411
+ end
412
+ end
413
+ end
414
+ rep.filter(:text_filter)
415
+ assert !rep.binary?
416
+ end
417
+
418
+ def test_converted_binary_rep_cannot_be_filtered_with_binary_filters
419
+ item = create_binary_item
420
+ site = mock_and_stub(
421
+ :items => [item],
422
+ :layouts => [],
423
+ :config => []
424
+ )
425
+ item.stubs(:site).returns(site)
426
+ rep = create_rep_for(item, :foo)
427
+ rep.assigns = {}
428
+ create_binary_filter
429
+
430
+ assert rep.binary?
431
+ def rep.filter_named(name)
432
+ @filter ||= Class.new(::Nanoc::Filter) do
433
+ type :binary => :text
434
+ def run(content, params={})
435
+ "Some textual content"
436
+ end
437
+ end
438
+ end
439
+ rep.filter(:binary_to_text)
440
+ refute rep.binary?
441
+ assert_raises(Nanoc::Errors::CannotUseBinaryFilter) { rep.filter(:binary_filter) }
442
+ end
443
+
444
+ def test_new_content_should_be_frozen
445
+ filter_class = Class.new(::Nanoc::Filter) do
446
+ def run(content, params={})
447
+ content.gsub!('foo', 'moo')
448
+ content
449
+ end
450
+ end
451
+
452
+ item = Nanoc::Item.new("foo bar", {}, '/foo/')
453
+ rep = Nanoc::ItemRep.new(item, :default)
454
+ rep.instance_eval { @filter_class = filter_class }
455
+ def rep.filter_named(name) ; @filter_class ; end
456
+
457
+ raised = false
458
+ begin
459
+ rep.filter(:whatever)
460
+ rescue => e
461
+ raised = true
462
+ assert_match /^can't modify frozen /, e.message
463
+ end
464
+ assert raised
465
+ end
466
+
467
+ def test_filter_should_freeze_content
468
+ filter_class = Class.new(::Nanoc::Filter) do
469
+ def run(content, params={})
470
+ content.gsub!('foo', 'moo')
471
+ content
472
+ end
473
+ end
474
+
475
+ item = Nanoc::Item.new("foo bar", {}, '/foo/')
476
+ rep = Nanoc::ItemRep.new(item, :default)
477
+ rep.instance_eval { @filter_class = filter_class }
478
+ def rep.filter_named(name) ; @filter_class ; end
479
+
480
+ raised = false
481
+ begin
482
+ rep.filter(:erb)
483
+ rep.filter(:whatever)
484
+ rescue => e
485
+ raised = true
486
+ assert_match /^can't modify frozen /, e.message
487
+ end
488
+ assert raised
489
+ end
490
+
491
+ def test_raw_path_should_generate_dependency
492
+ items = [
493
+ Nanoc3::Item.new("foo", {}, '/foo/'),
494
+ Nanoc3::Item.new("bar", {}, '/bar/')
495
+ ]
496
+ item_reps = [
497
+ Nanoc3::ItemRep.new(items[0], :default),
498
+ Nanoc3::ItemRep.new(items[1], :default)
499
+ ]
500
+
501
+ dt = Nanoc3::DependencyTracker.new(items)
502
+ dt.start
503
+ Nanoc3::NotificationCenter.post(:visit_started, items[0])
504
+ item_reps[1].raw_path
505
+ Nanoc3::NotificationCenter.post(:visit_ended, items[0])
506
+ dt.stop
507
+
508
+ assert_equal [ items[1] ], dt.objects_causing_outdatedness_of(items[0])
509
+ end
510
+
511
+ def test_path_should_generate_dependency
512
+ items = [
513
+ Nanoc3::Item.new("foo", {}, '/foo/'),
514
+ Nanoc3::Item.new("bar", {}, '/bar/')
515
+ ]
516
+ item_reps = [
517
+ Nanoc3::ItemRep.new(items[0], :default),
518
+ Nanoc3::ItemRep.new(items[1], :default)
519
+ ]
520
+
521
+ dt = Nanoc3::DependencyTracker.new(items)
522
+ dt.start
523
+ Nanoc3::NotificationCenter.post(:visit_started, items[0])
524
+ item_reps[1].path
525
+ Nanoc3::NotificationCenter.post(:visit_ended, items[0])
526
+ dt.stop
527
+
528
+ assert_equal [ items[1] ], dt.objects_causing_outdatedness_of(items[0])
529
+ end
530
+
531
+ private
532
+
533
+ def create_binary_item
534
+ Nanoc::Item.new(
535
+ "/a/file/name.dat", {}, '/',
536
+ :binary => true
537
+ )
538
+ end
539
+
540
+ def mock_and_stub(params)
541
+ m = mock
542
+ params.each do |method, return_value|
543
+ m.stubs(method.to_sym).returns( return_value )
544
+ end
545
+ m
546
+ end
547
+
548
+ def create_rep_for(item, name)
549
+ Nanoc::ItemRep.new(item, name)
550
+ end
551
+
552
+ def create_textual_filter
553
+ f = create_filter(:text)
554
+ f.class_eval do
555
+ def run(content, params={})
556
+ ""
557
+ end
558
+ end
559
+ f
560
+ end
561
+
562
+ def create_binary_filter
563
+ f = create_filter(:binary)
564
+ f.class_eval do
565
+ def run(content, params={})
566
+ File.open(output_filename, 'w') { |io| io.write(content) }
567
+ end
568
+ end
569
+ f
570
+ end
571
+
572
+ def create_filter(type)
573
+ filter_klass = Class.new(Nanoc::Filter)
574
+ filter_klass.type(type)
575
+ Nanoc::Filter.register filter_klass, "#{type}_filter".to_sym
576
+ filter_klass
577
+ end
578
+
579
+ end