ruhoh 2.5 → 2.6

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 (72) hide show
  1. data/Gemfile +1 -1
  2. data/bin/ruhoh +10 -3
  3. data/features/_root.feature +11 -0
  4. data/features/data.feature +78 -0
  5. data/features/javascripts.feature +36 -0
  6. data/features/permalinks.feature +23 -0
  7. data/features/plugins.feature +84 -0
  8. data/features/sort_order.feature +121 -0
  9. data/features/step_defs.rb +3 -3
  10. data/features/support/helpers.rb +3 -5
  11. data/history.json +21 -0
  12. data/lib/ruhoh.rb +28 -123
  13. data/lib/ruhoh/base/collectable.rb +273 -0
  14. data/lib/ruhoh/base/compilable.rb +30 -0
  15. data/lib/ruhoh/base/compilable_asset.rb +30 -0
  16. data/lib/ruhoh/base/model_viewable.rb +30 -0
  17. data/lib/ruhoh/base/modelable.rb +44 -0
  18. data/lib/ruhoh/base/page_like.rb +111 -0
  19. data/lib/ruhoh/base/page_viewable.rb +92 -0
  20. data/lib/ruhoh/base/routable.rb +20 -0
  21. data/lib/ruhoh/base/watchable.rb +18 -0
  22. data/lib/ruhoh/cascade.rb +93 -0
  23. data/lib/ruhoh/client.rb +1 -3
  24. data/lib/ruhoh/collections.rb +2 -1
  25. data/lib/ruhoh/config.rb +67 -0
  26. data/lib/ruhoh/console_methods.rb +0 -2
  27. data/lib/ruhoh/parse.rb +7 -5
  28. data/lib/ruhoh/plugins/initializer.rb +24 -0
  29. data/lib/ruhoh/plugins/local_plugins_plugin.rb +10 -0
  30. data/lib/ruhoh/plugins/plugin.rb +27 -0
  31. data/lib/ruhoh/programs/compile.rb +2 -6
  32. data/lib/ruhoh/programs/preview.rb +5 -2
  33. data/lib/ruhoh/programs/watch.rb +4 -6
  34. data/lib/ruhoh/publish/rsync.rb +2 -2
  35. data/lib/ruhoh/resources/_base/collection.rb +6 -0
  36. data/lib/ruhoh/resources/_base/compiler.rb +3 -0
  37. data/lib/ruhoh/resources/_base/model.rb +3 -0
  38. data/lib/ruhoh/resources/_base/model_view.rb +3 -0
  39. data/lib/ruhoh/resources/_base/watcher.rb +4 -0
  40. data/lib/ruhoh/resources/data/collection.rb +30 -9
  41. data/lib/ruhoh/resources/javascripts/collection_view.rb +5 -1
  42. data/lib/ruhoh/resources/javascripts/model_view.rb +15 -0
  43. data/lib/ruhoh/resources/layouts/client.rb +1 -1
  44. data/lib/ruhoh/resources/pages/client.rb +2 -2
  45. data/lib/ruhoh/resources/pages/collection.rb +2 -21
  46. data/lib/ruhoh/resources/theme/compiler.rb +2 -2
  47. data/lib/ruhoh/resources/widgets/collection.rb +2 -2
  48. data/lib/ruhoh/routes.rb +1 -1
  49. data/lib/ruhoh/summarizer.rb +2 -2
  50. data/lib/ruhoh/ui/dashboard.rb +13 -0
  51. data/lib/ruhoh/ui/page_not_found.rb +3 -2
  52. data/lib/ruhoh/url_slug.rb +23 -9
  53. data/lib/ruhoh/version.rb +1 -1
  54. data/lib/ruhoh/views/master_view.rb +1 -1
  55. data/spec/lib/ruhoh/plugins/initializer_spec.rb +43 -0
  56. data/spec/lib/ruhoh/plugins/plugin_spec.rb +40 -0
  57. data/spec/spec_helper.rb +1 -0
  58. data/system/config.json +21 -0
  59. data/system/{dash/index.html → dashboard.html} +1 -1
  60. data/{lib/ruhoh/ui → system}/page_not_found.html +0 -0
  61. data/system/plugins/sprockets/compiler.rb +1 -0
  62. data/system/widgets/comments/disqus.html +1 -1
  63. metadata +34 -15
  64. data/lib/ruhoh/base/collection.rb +0 -284
  65. data/lib/ruhoh/base/compiler.rb +0 -67
  66. data/lib/ruhoh/base/model.rb +0 -161
  67. data/lib/ruhoh/base/model_view.rb +0 -129
  68. data/lib/ruhoh/base/watcher.rb +0 -25
  69. data/lib/ruhoh/resources/dash/collection.rb +0 -10
  70. data/lib/ruhoh/resources/dash/model.rb +0 -5
  71. data/lib/ruhoh/resources/dash/model_view.rb +0 -5
  72. data/lib/ruhoh/resources/dash/previewer.rb +0 -13
@@ -8,7 +8,7 @@ module Ruhoh::Resources::Theme
8
8
  return unless setup_compilable
9
9
 
10
10
  self.files.each do |file|
11
- original_file = File.join(@ruhoh.paths.theme, file)
11
+ original_file = File.join(@ruhoh.cascade.theme, file)
12
12
  compiled_file = File.join(@collection.compiled_path, file)
13
13
  FileUtils.mkdir_p File.dirname(compiled_file)
14
14
  FileUtils.cp_r original_file, compiled_file
@@ -19,7 +19,7 @@ module Ruhoh::Resources::Theme
19
19
  # Returns list of all files from the theme to be compiled.
20
20
  # @returns[Array] relative filepaths
21
21
  def files
22
- FileUtils.cd(@ruhoh.paths.theme) {
22
+ FileUtils.cd(@ruhoh.cascade.theme) {
23
23
  return Dir["**/*"].select { |filepath|
24
24
  is_valid_asset?(filepath)
25
25
  }
@@ -4,8 +4,8 @@ module Ruhoh::Resources::Widgets
4
4
 
5
5
  def initialize(ruhoh)
6
6
  @ruhoh = ruhoh
7
- @path = File.join(@ruhoh.paths.base, "widgets")
8
- @system_path = File.join(@ruhoh.paths.system, "widgets")
7
+ @path = File.join(@ruhoh.cascade.base, "widgets")
8
+ @system_path = File.join(@ruhoh.cascade.system, "widgets")
9
9
  end
10
10
 
11
11
  def url_endpoint
@@ -28,7 +28,7 @@ class Ruhoh
28
28
 
29
29
  def routable
30
30
  @ruhoh.collections.all.keep_if do |r|
31
- @ruhoh.collections.collection(r).include?(Ruhoh::Resources::Pages::Routable) rescue false
31
+ @ruhoh.collections.collection(r).include?(Ruhoh::Base::Routable) rescue false
32
32
  end
33
33
  end
34
34
  end
@@ -23,7 +23,7 @@ class Ruhoh
23
23
 
24
24
  # Return a summary element if specified
25
25
  summary_el = content_doc.at_css('.' + SummaryNodeClassName)
26
- return summary_el.to_html if summary_el
26
+ return summary_el.to_html(:encoding => 'UTF-8') if summary_el
27
27
 
28
28
  # Create the summary element.
29
29
  summary_doc = Nokogiri::XML::Node.new("div", Nokogiri::HTML::Document.new)
@@ -59,7 +59,7 @@ class Ruhoh
59
59
  summary_doc << node
60
60
  end
61
61
 
62
- summary_doc.to_html
62
+ summary_doc.to_html(:encoding => 'UTF-8')
63
63
  end
64
64
  end
65
65
  end
@@ -0,0 +1,13 @@
1
+ class Ruhoh::UI::Dashboard
2
+ def initialize(ruhoh)
3
+ @ruhoh = ruhoh
4
+ end
5
+
6
+ def call(env)
7
+ path = @ruhoh.cascade.find_file('dashboard')['realpath']
8
+ template = File.open(path, 'r:UTF-8').read
9
+ view = @ruhoh.master_view({"content" => template })
10
+
11
+ [200, {'Content-Type' => 'text/html'}, [ view.content ]]
12
+ end
13
+ end
@@ -25,11 +25,12 @@ TEXT
25
25
  end
26
26
 
27
27
  def show
28
- template = File.open(File.join(File.dirname(__FILE__), 'page_not_found.html'), 'r:UTF-8').read
28
+ path = @ruhoh.cascade.find_file('page_not_found')['realpath']
29
+ template = File.open(path, 'r:UTF-8').read
29
30
  body = Mustache.render(template, {
30
31
  pointer: @pointer,
31
32
  url: @request.path,
32
- filepath: File.join(File.basename(@ruhoh.base), filepath),
33
+ filepath: File.join(File.basename(@ruhoh.cascade.base), filepath),
33
34
  content: Content
34
35
  })
35
36
 
@@ -20,15 +20,33 @@ class Ruhoh
20
20
 
21
21
  # @return[String] the dynamic URL with token substitution.
22
22
  def dynamic
23
- data.inject(@format) { |result, token|
24
- result.gsub(/:#{ Regexp.escape(token.first) }/, token.last)
25
- }.gsub(/\/+/, "/")
23
+ cache = data
24
+ result = @format
25
+ .gsub(/:[^\/\.]+/) { |a| cache[$&.gsub(':', '')] }
26
+ .gsub('//', '/')
27
+ .split('/')
28
+
29
+ # this is ugly but I'm out of ideas. Help!
30
+ last = result.pop
31
+ if uses_extension?
32
+ last = last
33
+ .split('.')
34
+ .map{ |a| Ruhoh::StringFormat.clean_slug_and_escape(a) }
35
+ .join('.')
36
+ else
37
+ last = Ruhoh::StringFormat.clean_slug_and_escape(last)
38
+ end
39
+
40
+ result
41
+ .map{ |a| Ruhoh::StringFormat.clean_slug_and_escape(a) }
42
+ .join('/') + "/#{ last }"
26
43
  end
27
44
 
28
45
  def data
29
- result = uses_date? ? date_data : {}
46
+ result = @page_data
47
+ result = result.merge(date_data) if uses_date?
48
+
30
49
  result.merge({
31
- "title" => title,
32
50
  "filename" => filename,
33
51
  "path" => path,
34
52
  "relative_path" => relative_path,
@@ -55,10 +73,6 @@ class Ruhoh
55
73
  )
56
74
  end
57
75
 
58
- def title
59
- Ruhoh::StringFormat.clean_slug_and_escape(@page_data['title'])
60
- end
61
-
62
76
  def filename
63
77
  File.basename(@page_data['id'], ext)
64
78
  end
@@ -1,4 +1,4 @@
1
1
  class Ruhoh
2
- Version = VERSION = '2.5'
2
+ Version = VERSION = '2.6'
3
3
  RuhohSpec = '2.1'
4
4
  end
@@ -51,7 +51,7 @@ module Ruhoh::Views
51
51
 
52
52
  def urls
53
53
  @ruhoh.collections.url_endpoints.merge({
54
- 'base_path' => @ruhoh.base_path,
54
+ 'base_path' => @ruhoh.config.base_path,
55
55
  'production' => @ruhoh.config["production_url"],
56
56
  'production_url' => @ruhoh.config["production_url"]
57
57
  })
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ module Ruhoh::Plugins
4
+ describe Initializer do
5
+ describe 'constructor' do
6
+ it 'raises an error when block is not defined' do
7
+ expect { Initializer.new 'foo' }.to raise_error ArgumentError
8
+ expect { Initializer.new('foo') { } }.to_not raise_error
9
+ end
10
+ end
11
+
12
+ describe '#run' do
13
+ it "raises an error when it's not bound" do
14
+ initializer = Initializer.new('foo') { }
15
+ expect { initializer.run }.to raise_error RuntimeError
16
+ expect { initializer.bind(self).run }.to_not raise_error
17
+ end
18
+
19
+ it 'executes the block in the bound context' do
20
+ initializer = Initializer.new('foo') do
21
+ self << 'a' if length == 1
22
+ end
23
+ obj = ['b']
24
+ expect { initializer.bind(obj).run }.to change(obj, :length).to 2
25
+ end
26
+
27
+ it 'passes given arguments to block' do
28
+ initializer = Initializer.new('foo') do |arg|
29
+ raise 'arg is absent' if arg != 'a'
30
+ end
31
+ expect { initializer.bind(self).run }.to raise_error 'arg is absent'
32
+ expect { initializer.run 'a' }.to_not raise_error
33
+ end
34
+ end
35
+
36
+ describe '#bind' do
37
+ it 'returns self' do
38
+ initializer = Initializer.new('foo') { }
39
+ initializer.bind(self).should == initializer
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ module Ruhoh::Plugins
4
+ describe Plugin do
5
+ describe '::initializers' do
6
+ it 'returns an array' do
7
+ Plugin.initializers.should be_a Array
8
+ end
9
+
10
+ it 'memoizes the array' do
11
+ Plugin.initializers.object_id.should == Plugin.initializers.object_id
12
+ end
13
+ end
14
+
15
+ context 'when included in a class' do
16
+ let(:instance_class) do
17
+ Class.new do
18
+ include Plugin
19
+ end
20
+ end
21
+
22
+ it 'defines the ::initializer method' do
23
+ instance_class.should respond_to :initializer
24
+ end
25
+
26
+ describe '::initializer' do
27
+ it 'appends to initializers collection' do
28
+ expect {
29
+ instance_class.initializer('foo') { }
30
+ }.to change(Plugin.initializers, :length).to 1
31
+ end
32
+
33
+ it 'appends an initializer object filled with given params' do
34
+ instance_class.initializer('foo') { }
35
+ Plugin.initializers.first.name.should == 'foo'
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1 @@
1
+ require File.expand_path '../../lib/ruhoh', __FILE__
@@ -0,0 +1,21 @@
1
+ {
2
+ "base_path" : "/"
3
+ ,
4
+ "date_format" : "%Y-%m-%d"
5
+ ,
6
+ "compiled_path" : "compiled"
7
+ ,
8
+ "compiled" : {
9
+ "use" : "ignore"
10
+ }
11
+ ,
12
+ "_root" : {
13
+ "permalink" : "/:relative_path/:filename",
14
+ "paginator" : {
15
+ "url" : "/index/"
16
+ },
17
+ "rss" : {
18
+ "url" : "/"
19
+ }
20
+ }
21
+ }
@@ -209,4 +209,4 @@
209
209
  Tabs.init();
210
210
  </script>
211
211
  </body>
212
- </html>
212
+ </html>
@@ -5,6 +5,7 @@ module Ruhoh::SprocketsPlugin
5
5
  extend Ruhoh::Base::CompilableAsset
6
6
  def run
7
7
  env = Sprockets::Environment.new
8
+ #env.css_compressor = :sass
8
9
  env.logger = Logger.new(STDOUT)
9
10
  env.logger.level = Logger::WARN
10
11
 
@@ -9,7 +9,7 @@ short_name : jekyllbootstrap # Change This!
9
9
  /* * * DON'T EDIT BELOW THIS LINE * * */
10
10
  (function() {
11
11
  var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
12
- dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
12
+ dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
13
13
  (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
14
14
  })();
15
15
  </script>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruhoh
3
3
  version: !ruby/object:Gem::Version
4
- version: '2.5'
4
+ version: '2.6'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-22 00:00:00.000000000 Z
12
+ date: 2013-12-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -151,6 +151,7 @@ files:
151
151
  - Rakefile
152
152
  - bin/ruhoh
153
153
  - cucumber.yml
154
+ - features/_root.feature
154
155
  - features/base_path.feature
155
156
  - features/categories.feature
156
157
  - features/config.feature
@@ -165,6 +166,8 @@ files:
165
166
  - features/pagination.feature
166
167
  - features/partials.feature
167
168
  - features/permalinks.feature
169
+ - features/plugins.feature
170
+ - features/sort_order.feature
168
171
  - features/static.feature
169
172
  - features/step_defs.rb
170
173
  - features/stylesheets.feature
@@ -178,34 +181,45 @@ files:
178
181
  - features/widgets/widgets.feature
179
182
  - history.json
180
183
  - lib/ruhoh.rb
181
- - lib/ruhoh/base/collection.rb
182
- - lib/ruhoh/base/compiler.rb
183
- - lib/ruhoh/base/model.rb
184
- - lib/ruhoh/base/model_view.rb
185
- - lib/ruhoh/base/watcher.rb
184
+ - lib/ruhoh/base/collectable.rb
185
+ - lib/ruhoh/base/compilable.rb
186
+ - lib/ruhoh/base/compilable_asset.rb
187
+ - lib/ruhoh/base/model_viewable.rb
188
+ - lib/ruhoh/base/modelable.rb
189
+ - lib/ruhoh/base/page_like.rb
190
+ - lib/ruhoh/base/page_viewable.rb
191
+ - lib/ruhoh/base/routable.rb
192
+ - lib/ruhoh/base/watchable.rb
186
193
  - lib/ruhoh/cache.rb
194
+ - lib/ruhoh/cascade.rb
187
195
  - lib/ruhoh/client.rb
188
196
  - lib/ruhoh/collections.rb
197
+ - lib/ruhoh/config.rb
189
198
  - lib/ruhoh/console_methods.rb
190
199
  - lib/ruhoh/converter.rb
191
200
  - lib/ruhoh/converters/markdown.rb
192
201
  - lib/ruhoh/friend.rb
193
202
  - lib/ruhoh/logger.rb
194
203
  - lib/ruhoh/parse.rb
204
+ - lib/ruhoh/plugins/initializer.rb
205
+ - lib/ruhoh/plugins/local_plugins_plugin.rb
206
+ - lib/ruhoh/plugins/plugin.rb
195
207
  - lib/ruhoh/programs/compile.rb
196
208
  - lib/ruhoh/programs/preview.rb
197
209
  - lib/ruhoh/programs/watch.rb
198
210
  - lib/ruhoh/publish/rsync.rb
199
- - lib/ruhoh/resources/dash/collection.rb
200
- - lib/ruhoh/resources/dash/model.rb
201
- - lib/ruhoh/resources/dash/model_view.rb
202
- - lib/ruhoh/resources/dash/previewer.rb
211
+ - lib/ruhoh/resources/_base/collection.rb
212
+ - lib/ruhoh/resources/_base/compiler.rb
213
+ - lib/ruhoh/resources/_base/model.rb
214
+ - lib/ruhoh/resources/_base/model_view.rb
215
+ - lib/ruhoh/resources/_base/watcher.rb
203
216
  - lib/ruhoh/resources/data/collection.rb
204
217
  - lib/ruhoh/resources/data/collection_view.rb
205
218
  - lib/ruhoh/resources/ignore/collection.rb
206
219
  - lib/ruhoh/resources/javascripts/collection.rb
207
220
  - lib/ruhoh/resources/javascripts/collection_view.rb
208
221
  - lib/ruhoh/resources/javascripts/compiler.rb
222
+ - lib/ruhoh/resources/javascripts/model_view.rb
209
223
  - lib/ruhoh/resources/layouts/client.rb
210
224
  - lib/ruhoh/resources/layouts/model.rb
211
225
  - lib/ruhoh/resources/media/collection.rb
@@ -233,7 +247,7 @@ files:
233
247
  - lib/ruhoh/string_format.rb
234
248
  - lib/ruhoh/summarizer.rb
235
249
  - lib/ruhoh/time.rb
236
- - lib/ruhoh/ui/page_not_found.html
250
+ - lib/ruhoh/ui/dashboard.rb
237
251
  - lib/ruhoh/ui/page_not_found.rb
238
252
  - lib/ruhoh/url_slug.rb
239
253
  - lib/ruhoh/utils.rb
@@ -245,10 +259,15 @@ files:
245
259
  - lib/ruhoh/views/master_view.rb
246
260
  - lib/ruhoh/views/rmustache.rb
247
261
  - ruhoh.gemspec
262
+ - spec/lib/ruhoh/plugins/initializer_spec.rb
263
+ - spec/lib/ruhoh/plugins/plugin_spec.rb
264
+ - spec/spec_helper.rb
248
265
  - system/_scaffold.html
249
- - system/dash/index.html
266
+ - system/config.json
267
+ - system/dashboard.html
250
268
  - system/layouts/_scaffold.html
251
269
  - system/layouts/paginator.html
270
+ - system/page_not_found.html
252
271
  - system/partials/categories_list.html
253
272
  - system/partials/pages_list.html
254
273
  - system/partials/posts_collate.html
@@ -285,7 +304,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
285
304
  version: '0'
286
305
  segments:
287
306
  - 0
288
- hash: 4393455842480950745
307
+ hash: -1883264674327180773
289
308
  required_rubygems_version: !ruby/object:Gem::Requirement
290
309
  none: false
291
310
  requirements:
@@ -294,7 +313,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
294
313
  version: '0'
295
314
  segments:
296
315
  - 0
297
- hash: 4393455842480950745
316
+ hash: -1883264674327180773
298
317
  requirements: []
299
318
  rubyforge_project:
300
319
  rubygems_version: 1.8.24
@@ -1,284 +0,0 @@
1
- module Ruhoh::Base
2
-
3
- module Collectable
4
-
5
- def self.included(klass)
6
- klass.__send__(:attr_accessor, :resource_name, :master)
7
- klass.__send__(:attr_reader, :ruhoh)
8
- end
9
-
10
- def initialize(ruhoh)
11
- @ruhoh = ruhoh
12
- end
13
-
14
- # Public API for finding a resource from this collection
15
- # @param name_or_pointer [String, Hash]
16
- # Hash - File pointer
17
- # String - id (filename) with full extension, e.g: about-me.md
18
- # String - name (filename) without the extension e.g: about-me
19
- # Returns the first matched filename.
20
- # See implementation for how match is determined.
21
- # @param opts [Hash] Optional options
22
- # opts[:all] - true to search all files as some may be invalid as resources
23
- #
24
- # @return[model, nil] the model is always wrapped in its view.
25
- def find(name_or_pointer, opts={})
26
- pointer = find_file(name_or_pointer, opts)
27
- return nil unless pointer
28
-
29
- @ruhoh.cache.get(pointer['realpath']) ||
30
- @ruhoh.cache.set(pointer['realpath'], load_model_view(pointer))
31
- end
32
-
33
- # Public API
34
- # @return[Hash] dictionary of models { "id" => Model }
35
- def dictionary
36
- dict = {}
37
- files.values.each { |pointer|
38
- dict.merge!({
39
- pointer['id'] => find(pointer)
40
- })
41
- }
42
- dict
43
- end
44
-
45
- def resource_name
46
- @resource_name ||= self.class.name.split("::").pop
47
- end
48
-
49
- # Implemented via Observable module
50
- # See http://ruby-doc.org/stdlib-1.9.3/libdoc/observer/rdoc/Observable.html
51
- # Collection subscribes to its child models.
52
- # #update is called on model #process.
53
- # noop
54
- def update(model_data)
55
- end
56
-
57
- # The default glob for finding files.
58
- # Every file in all child directories.
59
- def glob
60
- "**/*"
61
- end
62
-
63
- # Default paths to the 3 levels of the cascade.
64
- def paths
65
- Array(@ruhoh.cascade.map{|h| h["path"]}).map { |path|
66
- collection_path = File.join(path, resource_name)
67
- next unless File.directory?(collection_path)
68
-
69
- collection_path
70
- }.compact
71
- end
72
-
73
- # Does this resource have any valid paths to process?
74
- # A valid path may exist on any of the cascade levels.
75
- # False means there are no directories on any cascade level.
76
- # @returns[Boolean]
77
- def paths?
78
- !paths.empty?
79
- end
80
-
81
- def config
82
- config = @ruhoh.config[resource_name] || {}
83
- unless config.is_a?(Hash)
84
- Ruhoh.log.error("'#{resource_name}' config key in config" +
85
- " is a #{config.class}; it needs to be a Hash (object).")
86
- end
87
- config
88
- end
89
-
90
- # NOOP
91
- # touch a model.
92
- # Used to perform custom regeneration logic against a model.
93
- def touch(name_or_pointer)
94
- end
95
-
96
- # @param key [String, Hash]
97
- # String - id (filename) with full extension, e.g: about-me.md
98
- # String - name (filename) without the extension e.g: about-me
99
- # Returns the first matched filename.
100
- # See implementation for how match is determined.
101
- # Hash - File pointer
102
- #
103
- # @param opts [Hash] Optional options
104
- # opts[:all] - true to search all files as some may be invalid as resources
105
- #
106
- # @return [pointer, nil]
107
- def find_file(key, opts={})
108
- return key if key.is_a?(Hash) # assume valid pointer
109
-
110
- dict = opts[:all] ? _all_files : files
111
-
112
- dict[key] || dict.values.find{ |a| key == a['id'].gsub(/.[^.]+$/, '') }
113
- end
114
-
115
- # Collect all files (as mapped by data resources) for this data endpoint.
116
- # Each resource can have 3 file references, one per each cascade level.
117
- # The file hashes are collected in order
118
- # so they will overwrite eachother if found.
119
-
120
- # @param id [String, Array] Optional.
121
- # Collect all files for a single data resource.
122
- # Can be many files due to the cascade.
123
- # @param [block] Optional.
124
- # Implement custom validation logic by passing in a block.
125
- # The block is given (id, self) as args.
126
- # Return true/false for whether the file is valid/invalid.
127
- #
128
- # @return[Hash] dictionary of pointers.
129
- def files(id=nil, &block)
130
- return @ruhoh.cache.get(files_cache_key) if @ruhoh.cache.get(files_cache_key)
131
-
132
- dict = _all_files
133
- dict.keep_if do |id, pointer|
134
- block_given? ? yield(id, self) : valid_file?(id)
135
- end
136
-
137
- @ruhoh.cache.set(files_cache_key, dict)
138
- dict
139
- end
140
-
141
- # Collect all files within this collection, valid or otherwise.
142
- # Each resource can have 3 file references, one per each cascade level.
143
- # The file hashes are collected in order and overwrite eachother if found.
144
- # This is a low-level method, see #files for the public interface.
145
- #
146
- # @return[Hash] dictionary of pointers.
147
- def _all_files
148
- dict = {}
149
- paths.each do |path|
150
- FileUtils.cd(path) {
151
- Dir[glob].each { |id|
152
- next unless File.exist?(id) && FileTest.file?(id)
153
- dict[id] = {
154
- "id" => id,
155
- "realpath" => File.realpath(id),
156
- "resource" => resource_name,
157
- }
158
- }
159
- }
160
- end
161
-
162
- dict
163
- end
164
-
165
- def valid_file?(filepath)
166
- return false if filepath.start_with?('.')
167
- return false if filepath.start_with?('_')
168
- excludes = Array(config['exclude']).map { |node| Regexp.new(node) }
169
- excludes.each { |regex| return false if filepath =~ regex }
170
- true
171
- end
172
-
173
- %w{
174
- collection_view
175
- model
176
- model_view
177
- client
178
- compiler
179
- watcher
180
- previewer
181
- }.each do |method_name|
182
- define_method(method_name) do
183
- get_module_namespace.const_get(camelize(method_name).to_sym)
184
- end
185
-
186
- define_method("#{method_name}?") do
187
- get_module_namespace.const_defined?(camelize(method_name).to_sym)
188
- end
189
- end
190
-
191
- def load_collection_view
192
- @_collection_view ||= collection_view? ?
193
- collection_view.new(self) :
194
- self
195
- end
196
-
197
- def load_model(pointer)
198
- _model = model? ?
199
- model.new(@ruhoh, pointer) :
200
- Ruhoh::Base::Model.new(@ruhoh, pointer)
201
- _model.add_observer(self)
202
- _model
203
- end
204
-
205
- def load_model_view(pointer)
206
- model_view? ?
207
- model_view.new(load_model(pointer)) :
208
- Ruhoh::Base::ModelView.new(load_model(pointer))
209
- end
210
-
211
- def load_client(opts)
212
- @_client ||= client.new(load_collection_view, opts)
213
- end
214
-
215
- def load_compiler
216
- @_compiler ||= compiler.new(load_collection_view)
217
- end
218
-
219
- def load_watcher(*args)
220
- @_watcher ||= watcher? ?
221
- watcher.new(load_collection_view) :
222
- Ruhoh::Base::Watcher.new(load_collection_view)
223
- end
224
-
225
- def load_previewer(*args)
226
- @_previewer ||= previewer.new(@ruhoh)
227
- end
228
-
229
- def files_cache_key
230
- "#{ resource_name }-files"
231
- end
232
-
233
- def scaffold
234
- pointer = find_file('_scaffold', all: true) || @ruhoh.find_file('_scaffold')
235
- return '' unless pointer
236
-
237
- File.open(pointer['realpath'], 'r:UTF-8') { |f| f.read }
238
- end
239
-
240
- def compiled_path
241
- @compiled_path ||= @ruhoh.compiled_path(@ruhoh.to_url(url_endpoint))
242
- end
243
-
244
- protected
245
-
246
- # Load the registered resource else default to Pages if not configured.
247
- # @returns[Constant] the resource's module namespace
248
- def get_module_namespace
249
- type = @ruhoh.config[resource_name]["use"] rescue nil
250
- if type
251
- if @ruhoh.collections.registered.include?(type)
252
- Ruhoh::Resources.const_get(camelize(type))
253
- elsif @ruhoh.collections.base.include?(type)
254
- Ruhoh::Base.const_get(camelize(type))
255
- else
256
- klass = camelize(type)
257
- Friend.say {
258
- red "#{resource_name} resource set to use:'#{type}' in config" +
259
- " but Ruhoh::Resources::#{klass} does not exist."
260
- }
261
- abort
262
- end
263
- else
264
- if @ruhoh.collections.registered.include?(resource_name)
265
- Ruhoh::Resources.const_get(camelize(resource_name))
266
- else
267
- Ruhoh::Resources.const_get(:Pages)
268
- end
269
- end
270
- end
271
-
272
- def camelize(name)
273
- name.to_s.split('_').map { |a| a.capitalize }.join
274
- end
275
- end
276
-
277
- # Generic base implementation of a Collection class.
278
- # All collections use this class by default
279
- # unless the Collection class is explicitly defined for the resource.
280
- class Collection
281
- include Collectable
282
- end
283
-
284
- end