nanoc 3.2.4 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
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,536 @@
1
+ # encoding: utf-8
2
+
3
+ class Nanoc::DataSources::FilesystemUnifiedTest < MiniTest::Unit::TestCase
4
+
5
+ include Nanoc::TestHelpers
6
+
7
+ def new_data_source(params=nil)
8
+ # Mock site
9
+ site = Nanoc::Site.new({})
10
+
11
+ # Create data source
12
+ data_source = Nanoc::DataSources::FilesystemUnified.new(site, nil, nil, params)
13
+
14
+ # Done
15
+ data_source
16
+ end
17
+
18
+ def test_create_object_not_at_root
19
+ # Create item
20
+ data_source = new_data_source
21
+ data_source.send(:create_object, 'foobar', 'content here', { :foo => 'bar' }, '/asdf/')
22
+
23
+ # Check file existance
24
+ assert File.directory?('foobar')
25
+ assert !File.directory?('foobar/content')
26
+ assert !File.directory?('foobar/asdf')
27
+ assert File.file?('foobar/asdf.html')
28
+
29
+ # Check file content
30
+ expected = /^--- ?\nfoo: bar\n---\n\ncontent here$/
31
+ assert_match expected, File.read('foobar/asdf.html')
32
+ end
33
+
34
+ def test_create_object_at_root
35
+ # Create item
36
+ data_source = new_data_source
37
+ data_source.send(:create_object, 'foobar', 'content here', { :foo => 'bar' }, '/')
38
+
39
+ # Check file existance
40
+ assert File.directory?('foobar')
41
+ assert !File.directory?('foobar/index')
42
+ assert !File.directory?('foobar/foobar')
43
+ assert File.file?('foobar/index.html')
44
+
45
+ # Check file content
46
+ expected = /^--- ?\nfoo: bar\n---\n\ncontent here$/
47
+ assert_match expected, File.read('foobar/index.html')
48
+ end
49
+
50
+ def test_load_objects
51
+ # Create data source
52
+ data_source = new_data_source
53
+
54
+ # Create a fake class
55
+ klass = Class.new do
56
+ attr_reader :stuff
57
+ def initialize(*stuff)
58
+ @stuff = stuff
59
+ end
60
+ def ==(other)
61
+ @stuff == other.stuff
62
+ end
63
+ end
64
+
65
+ # Create sample files
66
+ FileUtils.mkdir_p('foo')
67
+ FileUtils.mkdir_p('foo/a/b')
68
+ File.open('foo/bar.html', 'w') { |io| io.write("---\nnum: 1\n---\ntest 1") }
69
+ File.open('foo/b.c.html', 'w') { |io| io.write("---\nnum: 2\n---\ntest 2") }
70
+ File.open('foo/a/b/c.html', 'w') { |io| io.write("---\nnum: 3\n---\ntest 3") }
71
+ File.open('foo/ugly.html~', 'w') { |io| io.write("---\nnum: 4\n---\ntest 4") }
72
+ File.open('foo/ugly.html.orig', 'w') { |io| io.write("---\nnum: 5\n---\ntest 5") }
73
+ File.open('foo/ugly.html.rej', 'w') { |io| io.write("---\nnum: 6\n---\ntest 6") }
74
+ File.open('foo/ugly.html.bak', 'w') { |io| io.write("---\nnum: 7\n---\ntest 7") }
75
+
76
+ # Get expected and actual output
77
+ expected_out = [
78
+ klass.new(
79
+ 'test 1',
80
+ { 'num' => 1, :filename => 'foo/bar.html', :extension => 'html', :file => File.open('foo/bar.html') },
81
+ '/bar/',
82
+ :binary => false, :mtime => File.mtime('foo/bar.html')
83
+ ),
84
+ klass.new(
85
+ 'test 2',
86
+ { 'num' => 2, :filename => 'foo/b.c.html', :extension => 'c.html', :file => File.open('foo/b.c.html') },
87
+ '/b/',
88
+ :binary => false, :mtime => File.mtime('foo/b.c.html')
89
+ ),
90
+ klass.new(
91
+ 'test 3',
92
+ { 'num' => 3, :filename => 'foo/a/b/c.html', :extension => 'html', :file => File.open('foo/a/b/c.html') },
93
+ '/a/b/c/',
94
+ :binary => false, :mtime => File.mtime('foo/a/b/c.html')
95
+ )
96
+ ]
97
+ actual_out = data_source.send(:load_objects, 'foo', 'The Foo', klass).sort_by { |i| i.stuff[0] }
98
+
99
+ # Check
100
+ (0..expected_out.size-1).each do |i|
101
+ assert_equal expected_out[i].stuff[0], actual_out[i].stuff[0], 'content must match'
102
+ assert_equal expected_out[i].stuff[2], actual_out[i].stuff[2], 'identifier must match'
103
+ assert_equal expected_out[i].stuff[3][:mtime], actual_out[i].stuff[3][:mtime], 'mtime must match'
104
+ assert_equal expected_out[i].stuff[1][:file].path, actual_out[i].stuff[1][:file].path, 'file paths must match'
105
+ expected_out[i].stuff[1][:file].close;
106
+ actual_out[i].stuff[1][:file].close
107
+ [ 'num', :filename, :extension ].each do |key|
108
+ assert_equal expected_out[i].stuff[1][key], actual_out[i].stuff[1][key], "attribute key #{key} must match"
109
+ end
110
+ end
111
+ end
112
+
113
+ def test_load_binary_objects
114
+ # Create data source
115
+ data_source = new_data_source
116
+
117
+ # Create sample files
118
+ FileUtils.mkdir_p('foo')
119
+ File.open('foo/stuff.dat', 'w') { |io| io.write("random binary data") }
120
+
121
+ # Load
122
+ items = data_source.send(:load_objects, 'foo', 'item', Nanoc::Item)
123
+
124
+ # Check
125
+ assert_equal 1, items.size
126
+ assert items[0].binary?
127
+ assert_equal 'foo/stuff.dat', items[0].raw_filename
128
+ assert_nil items[0].raw_content
129
+ end
130
+
131
+ def test_load_binary_layouts
132
+ # Create data source
133
+ data_source = new_data_source
134
+
135
+ # Create sample files
136
+ FileUtils.mkdir_p('foo')
137
+ File.open('foo/stuff.dat', 'w') { |io| io.write("random binary data") }
138
+
139
+ # Load
140
+ items = data_source.send(:load_objects, 'foo', 'item', Nanoc::Layout)
141
+
142
+ # Check
143
+ assert_equal 1, items.size
144
+ assert_equal 'random binary data', items[0].raw_content
145
+ end
146
+
147
+ def test_identifier_for_filename_allowing_periods_in_identifiers
148
+ # Create data source
149
+ data_source = new_data_source(:allow_periods_in_identifiers => true)
150
+
151
+ # Get input and expected output
152
+ expected = {
153
+ '/foo' => '/foo/',
154
+ '/foo.html' => '/foo/',
155
+ '/foo/index.html' => '/foo/',
156
+ '/foo.entry.html' => '/foo.entry/'
157
+ }
158
+
159
+ # Check
160
+ expected.each_pair do |input, expected_output|
161
+ actual_output = data_source.send(:identifier_for_filename, input)
162
+ assert_equal(
163
+ expected_output, actual_output,
164
+ "identifier_for_filename(#{input.inspect}) should equal #{expected_output.inspect}, not #{actual_output.inspect}"
165
+ )
166
+ end
167
+ end
168
+
169
+ def test_identifier_for_filename_disallowing_periods_in_identifiers
170
+ # Create data source
171
+ data_source = new_data_source
172
+
173
+ # Get input and expected output
174
+ expected = {
175
+ '/foo' => '/foo/',
176
+ '/foo.html' => '/foo/',
177
+ '/foo/index.html' => '/foo/',
178
+ '/foo.html.erb' => '/foo/'
179
+ }
180
+
181
+ # Check
182
+ expected.each_pair do |input, expected_output|
183
+ actual_output = data_source.send(:identifier_for_filename, input)
184
+ assert_equal(
185
+ expected_output, actual_output,
186
+ "identifier_for_filename(#{input.inspect}) should equal #{expected_output.inspect}, not #{actual_output.inspect}"
187
+ )
188
+ end
189
+ end
190
+
191
+ def test_identifier_for_filename_with_subfilename_allowing_periods_in_identifiers
192
+ expectations = {
193
+ 'foo/bar.yaml' => '/foo/bar/',
194
+ 'foo/quxbar.yaml' => '/foo/quxbar/',
195
+ 'foo/barqux.yaml' => '/foo/barqux/',
196
+ 'foo/quxbarqux.yaml' => '/foo/quxbarqux/',
197
+ 'foo/qux.bar.yaml' => '/foo/qux.bar/',
198
+ 'foo/bar.qux.yaml' => '/foo/bar.qux/',
199
+ 'foo/qux.bar.qux.yaml' => '/foo/qux.bar.qux/',
200
+ 'foo/index.yaml' => '/foo/',
201
+ 'index.yaml' => '/',
202
+ 'foo/blah_index.yaml' => '/foo/blah_index/'
203
+ }
204
+
205
+ data_source = new_data_source(:allow_periods_in_identifiers => true)
206
+ expectations.each_pair do |meta_filename, expected_identifier|
207
+ content_filename = meta_filename.sub(/yaml$/, 'html')
208
+ [ meta_filename, content_filename ].each do |filename|
209
+ assert_equal(
210
+ expected_identifier,
211
+ data_source.instance_eval { identifier_for_filename(filename) }
212
+ )
213
+ end
214
+ end
215
+ end
216
+
217
+ def test_identifier_for_filename_with_subfilename_disallowing_periods_in_identifiers
218
+ expectations = {
219
+ 'foo/bar.yaml' => '/foo/bar/',
220
+ 'foo/quxbar.yaml' => '/foo/quxbar/',
221
+ 'foo/barqux.yaml' => '/foo/barqux/',
222
+ 'foo/quxbarqux.yaml' => '/foo/quxbarqux/',
223
+ 'foo/qux.bar.yaml' => '/foo/qux/',
224
+ 'foo/bar.qux.yaml' => '/foo/bar/',
225
+ 'foo/qux.bar.qux.yaml' => '/foo/qux/',
226
+ 'foo/index.yaml' => '/foo/',
227
+ 'index.yaml' => '/',
228
+ 'foo/blah_index.yaml' => '/foo/blah_index/'
229
+ }
230
+
231
+ data_source = new_data_source
232
+ expectations.each_pair do |meta_filename, expected_identifier|
233
+ content_filename = meta_filename.sub(/yaml$/, 'html')
234
+ [ meta_filename, content_filename ].each do |filename|
235
+ assert_equal(
236
+ expected_identifier,
237
+ data_source.instance_eval { identifier_for_filename(filename) }
238
+ )
239
+ end
240
+ end
241
+ end
242
+
243
+ def test_load_objects_allowing_periods_in_identifiers
244
+ # Create data source
245
+ data_source = new_data_source(:allow_periods_in_identifiers => true)
246
+
247
+ # Create a fake class
248
+ klass = Class.new do
249
+ attr_reader :stuff
250
+ def initialize(*stuff)
251
+ @stuff = stuff
252
+ end
253
+ def ==(other)
254
+ @stuff == other.stuff
255
+ end
256
+ end
257
+
258
+ # Create sample files
259
+ FileUtils.mkdir_p('foo')
260
+ FileUtils.mkdir_p('foo/a/b')
261
+ File.open('foo/a/b/c.yaml', 'w') { |io| io.write("---\nnum: 1\n") }
262
+ File.open('foo/b.c.yaml', 'w') { |io| io.write("---\nnum: 2\n") }
263
+ File.open('foo/b.c.html', 'w') { |io| io.write("test 2") }
264
+ File.open('foo/car.html', 'w') { |io| io.write("test 3") }
265
+ File.open('foo/ugly.yaml~', 'w') { |io| io.write("blah") }
266
+ File.open('foo/ugly.html~', 'w') { |io| io.write("blah") }
267
+ File.open('foo/ugly.html.orig', 'w') { |io| io.write("blah") }
268
+ File.open('foo/ugly.html.rej', 'w') { |io| io.write("blah") }
269
+ File.open('foo/ugly.html.bak', 'w') { |io| io.write("blah") }
270
+
271
+ # Get expected output
272
+ expected_out = [
273
+ klass.new(
274
+ '',
275
+ {
276
+ 'num' => 1,
277
+ :content_filename => nil,
278
+ :meta_filename => 'foo/a/b/c.yaml',
279
+ :extension => nil,
280
+ :file => nil
281
+ },
282
+ '/a/b/c/',
283
+ :binary => false, :mtime => File.mtime('foo/a/b/c.yaml')
284
+ ),
285
+ klass.new(
286
+ 'test 2',
287
+ {
288
+ 'num' => 2,
289
+ :content_filename => 'foo/b.c.html',
290
+ :meta_filename => 'foo/b.c.yaml',
291
+ :extension => 'html',
292
+ :file => File.open('foo/b.c.html')
293
+ },
294
+ '/b.c/',
295
+ :binary => false, :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')
296
+ ),
297
+ klass.new(
298
+ 'test 3',
299
+ {
300
+ :content_filename => 'foo/car.html',
301
+ :meta_filename => nil,
302
+ :extension => 'html',
303
+ :file => File.open('foo/car.html')
304
+ },
305
+ '/car/',
306
+ :binary => false, :mtime => File.mtime('foo/car.html')
307
+ )
308
+ ]
309
+
310
+ # Get actual output ordered by identifier
311
+ actual_out = data_source.send(:load_objects, 'foo', 'The Foo', klass).sort_by { |i| i.stuff[2] }
312
+
313
+ # Check
314
+ (0..expected_out.size-1).each do |i|
315
+ assert_equal expected_out[i].stuff[0], actual_out[i].stuff[0], 'content must match'
316
+ assert_equal expected_out[i].stuff[2], actual_out[i].stuff[2], 'identifier must match'
317
+ assert_equal expected_out[i].stuff[3][:mtime], actual_out[i].stuff[3][:mtime], 'mtime must match'
318
+
319
+ actual_file = actual_out[i].stuff[1][:file]
320
+ expected_file = expected_out[i].stuff[1][:file]
321
+ assert(actual_file == expected_file || actual_file.path == expected_file.path, 'file paths must match')
322
+ actual_file.close unless actual_file.nil?
323
+ expected_file.close unless expected_file.nil?
324
+
325
+ [ 'num', :content_filename, :meta_filename, :extension ].each do |key|
326
+ assert_equal expected_out[i].stuff[1][key], actual_out[i].stuff[1][key], "attribute key #{key} must match"
327
+ end
328
+ end
329
+ end
330
+
331
+ def test_load_objects_disallowing_periods_in_identifiers
332
+ # Create data source
333
+ data_source = new_data_source
334
+
335
+ # Create a fake class
336
+ klass = Class.new do
337
+ attr_reader :stuff
338
+ def initialize(*stuff)
339
+ @stuff = stuff
340
+ end
341
+ def ==(other)
342
+ @stuff == other.stuff
343
+ end
344
+ end
345
+
346
+ # Create sample files
347
+ FileUtils.mkdir_p('foo')
348
+ FileUtils.mkdir_p('foo/a/b')
349
+ File.open('foo/a/b/c.yaml', 'w') { |io| io.write("---\nnum: 1\n") }
350
+ File.open('foo/b.yaml', 'w') { |io| io.write("---\nnum: 2\n") }
351
+ File.open('foo/b.html.erb', 'w') { |io| io.write("test 2") }
352
+ File.open('foo/car.html', 'w') { |io| io.write("test 3") }
353
+ File.open('foo/ugly.yaml~', 'w') { |io| io.write("blah") }
354
+ File.open('foo/ugly.html~', 'w') { |io| io.write("blah") }
355
+ File.open('foo/ugly.html.orig', 'w') { |io| io.write("blah") }
356
+ File.open('foo/ugly.html.rej', 'w') { |io| io.write("blah") }
357
+ File.open('foo/ugly.html.bak', 'w') { |io| io.write("blah") }
358
+
359
+ # Get expected output
360
+ expected_out = [
361
+ klass.new(
362
+ '',
363
+ {
364
+ 'num' => 1,
365
+ :content_filename => nil,
366
+ :meta_filename => 'foo/a/b/c.yaml',
367
+ :extension => nil,
368
+ :file => nil
369
+ },
370
+ '/a/b/c/',
371
+ :binary => false, :mtime => File.mtime('foo/a/b/c.yaml')
372
+ ),
373
+ klass.new(
374
+ 'test 2',
375
+ {
376
+ 'num' => 2,
377
+ :content_filename => 'foo/b.html.erb',
378
+ :meta_filename => 'foo/b.yaml',
379
+ :extension => 'html.erb',
380
+ :file => File.open('foo/b.html.erb')
381
+ },
382
+ '/b/',
383
+ :binary => false, :mtime => File.mtime('foo/b.html.erb') > File.mtime('foo/b.yaml') ? File.mtime('foo/b.html.erb') : File.mtime('foo/b.yaml')
384
+ ),
385
+ klass.new(
386
+ 'test 3',
387
+ {
388
+ :content_filename => 'foo/car.html',
389
+ :meta_filename => nil,
390
+ :extension => 'html',
391
+ :file => File.open('foo/car.html')
392
+ },
393
+ '/car/',
394
+ :binary => false, :mtime => File.mtime('foo/car.html')
395
+ )
396
+ ]
397
+
398
+ # Get actual output ordered by identifier
399
+ actual_out = data_source.send(:load_objects, 'foo', 'The Foo', klass).sort_by { |i| i.stuff[2] }
400
+
401
+ # Check
402
+ (0..expected_out.size-1).each do |i|
403
+ assert_equal expected_out[i].stuff[0], actual_out[i].stuff[0], 'content must match'
404
+ assert_equal expected_out[i].stuff[2], actual_out[i].stuff[2], 'identifier must match'
405
+ assert_equal expected_out[i].stuff[3][:mtime], actual_out[i].stuff[3][:mtime], 'mtime must match'
406
+
407
+ actual_file = actual_out[i].stuff[1][:file]
408
+ expected_file = expected_out[i].stuff[1][:file]
409
+ assert(actual_file == expected_file || actual_file.path == expected_file.path, 'file paths must match')
410
+ actual_file.close unless actual_file.nil?
411
+ expected_file.close unless expected_file.nil?
412
+
413
+ [ 'num', :content_filename, :meta_filename, :extension ].each do |key|
414
+ assert_equal expected_out[i].stuff[1][key], actual_out[i].stuff[1][key], "attribute key #{key} must match"
415
+ end
416
+ end
417
+ end
418
+
419
+ def test_create_object_allowing_periods_in_identifiers
420
+ # Create data source
421
+ data_source = new_data_source(:allow_periods_in_identifiers => true)
422
+
423
+ # Create object without period
424
+ data_source.send(:create_object, 'foo', 'some content', { :some => 'attributes' }, '/asdf/')
425
+ assert File.file?('foo/asdf.html')
426
+ data = data_source.send(:parse, 'foo/asdf.html', nil, 'moo')
427
+ assert_equal({ 'some' => 'attributes' }, data[0])
428
+ assert_equal('some content', data[1])
429
+
430
+ # Create object with period
431
+ data_source.send(:create_object, 'foo', 'some content', { :some => 'attributes' }, '/as.df/')
432
+ assert File.file?('foo/as.df.html')
433
+ data = data_source.send(:parse, 'foo/as.df.html', nil, 'moo')
434
+ assert_equal({ 'some' => 'attributes' }, data[0])
435
+ assert_equal('some content', data[1])
436
+ end
437
+
438
+ def test_create_object_disallowing_periods_in_identifiers
439
+ # Create data source
440
+ data_source = new_data_source
441
+
442
+ # Create object without period
443
+ data_source.send(:create_object, 'foo', 'some content', { :some => 'attributes' }, '/asdf/')
444
+ assert File.file?('foo/asdf.html')
445
+ data = data_source.send(:parse, 'foo/asdf.html', nil, 'moo')
446
+ assert_equal({ 'some' => 'attributes' }, data[0])
447
+ assert_equal('some content', data[1])
448
+
449
+ # Create object with period
450
+ assert_raises(RuntimeError) do
451
+ data_source.send(:create_object, 'foo', 'some content', { :some => 'attributes' }, '/as.df/')
452
+ end
453
+ end
454
+
455
+ def test_filename_for
456
+ data_source = new_data_source
457
+
458
+ assert_equal '/foo.bar', data_source.send(:filename_for, '/foo', 'bar')
459
+ assert_equal '/foo.bar.baz', data_source.send(:filename_for, '/foo', 'bar.baz')
460
+ assert_equal '/foo', data_source.send(:filename_for, '/foo', '')
461
+ assert_equal nil, data_source.send(:filename_for, '/foo', nil)
462
+ end
463
+
464
+ def test_compile_huge_site
465
+ if_implemented do
466
+ # Create data source
467
+ data_source = new_data_source
468
+
469
+ # Create a lot of items
470
+ count = Process.getrlimit(Process::RLIMIT_NOFILE)[0] + 5
471
+ count.times do |i|
472
+ FileUtils.mkdir_p("content/#{i}")
473
+ File.open("content/#{i}/#{i}.html", 'w') { |io| io << "This is item #{i}." }
474
+ File.open("content/#{i}/#{i}.yaml", 'w') { |io| io << "title: Item #{i}" }
475
+ end
476
+
477
+ # Read all items
478
+ data_source.items
479
+ end
480
+ end
481
+
482
+ def test_compile_iso_8859_1_site
483
+ # Check encoding
484
+ if !''.respond_to?(:encode)
485
+ skip "Test only works on 1.9.x"
486
+ return
487
+ end
488
+
489
+ # Create data source
490
+ data_source = new_data_source
491
+
492
+ # Create item
493
+ data_source.create_item("Hëllö", {}, '/foo/')
494
+
495
+ # Parse
496
+ begin
497
+ original_default_external_encoding = Encoding.default_external
498
+ Encoding.default_external = 'ISO-8859-1'
499
+
500
+ items = data_source.items
501
+
502
+ assert_equal 1, items.size
503
+ assert_equal Encoding.find("UTF-8"), items[0].raw_content.encoding
504
+ ensure
505
+ Encoding.default_external = original_default_external_encoding
506
+ end
507
+ end
508
+
509
+ def test_compile_iso_8859_1_site_with_explicit_encoding
510
+ # Check encoding
511
+ if !''.respond_to?(:encode)
512
+ skip "Test only works on 1.9.x"
513
+ return
514
+ end
515
+
516
+ # Create data source
517
+ data_source = new_data_source({})
518
+ data_source.config[:encoding] = 'ISO-8859-1'
519
+
520
+ # Create item
521
+ begin
522
+ original_default_external_encoding = Encoding.default_external
523
+ Encoding.default_external = 'ISO-8859-1'
524
+
525
+ data_source.create_item("Hëllö", {}, '/foo/')
526
+ ensure
527
+ Encoding.default_external = original_default_external_encoding
528
+ end
529
+
530
+ # Parse
531
+ items = data_source.items
532
+ assert_equal 1, items.size
533
+ assert_equal Encoding.find("UTF-8"), items[0].raw_content.encoding
534
+ end
535
+
536
+ end