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.
- data/Gemfile +1 -1
- data/bin/ruhoh +10 -3
- data/features/_root.feature +11 -0
- data/features/data.feature +78 -0
- data/features/javascripts.feature +36 -0
- data/features/permalinks.feature +23 -0
- data/features/plugins.feature +84 -0
- data/features/sort_order.feature +121 -0
- data/features/step_defs.rb +3 -3
- data/features/support/helpers.rb +3 -5
- data/history.json +21 -0
- data/lib/ruhoh.rb +28 -123
- data/lib/ruhoh/base/collectable.rb +273 -0
- data/lib/ruhoh/base/compilable.rb +30 -0
- data/lib/ruhoh/base/compilable_asset.rb +30 -0
- data/lib/ruhoh/base/model_viewable.rb +30 -0
- data/lib/ruhoh/base/modelable.rb +44 -0
- data/lib/ruhoh/base/page_like.rb +111 -0
- data/lib/ruhoh/base/page_viewable.rb +92 -0
- data/lib/ruhoh/base/routable.rb +20 -0
- data/lib/ruhoh/base/watchable.rb +18 -0
- data/lib/ruhoh/cascade.rb +93 -0
- data/lib/ruhoh/client.rb +1 -3
- data/lib/ruhoh/collections.rb +2 -1
- data/lib/ruhoh/config.rb +67 -0
- data/lib/ruhoh/console_methods.rb +0 -2
- data/lib/ruhoh/parse.rb +7 -5
- data/lib/ruhoh/plugins/initializer.rb +24 -0
- data/lib/ruhoh/plugins/local_plugins_plugin.rb +10 -0
- data/lib/ruhoh/plugins/plugin.rb +27 -0
- data/lib/ruhoh/programs/compile.rb +2 -6
- data/lib/ruhoh/programs/preview.rb +5 -2
- data/lib/ruhoh/programs/watch.rb +4 -6
- data/lib/ruhoh/publish/rsync.rb +2 -2
- data/lib/ruhoh/resources/_base/collection.rb +6 -0
- data/lib/ruhoh/resources/_base/compiler.rb +3 -0
- data/lib/ruhoh/resources/_base/model.rb +3 -0
- data/lib/ruhoh/resources/_base/model_view.rb +3 -0
- data/lib/ruhoh/resources/_base/watcher.rb +4 -0
- data/lib/ruhoh/resources/data/collection.rb +30 -9
- data/lib/ruhoh/resources/javascripts/collection_view.rb +5 -1
- data/lib/ruhoh/resources/javascripts/model_view.rb +15 -0
- data/lib/ruhoh/resources/layouts/client.rb +1 -1
- data/lib/ruhoh/resources/pages/client.rb +2 -2
- data/lib/ruhoh/resources/pages/collection.rb +2 -21
- data/lib/ruhoh/resources/theme/compiler.rb +2 -2
- data/lib/ruhoh/resources/widgets/collection.rb +2 -2
- data/lib/ruhoh/routes.rb +1 -1
- data/lib/ruhoh/summarizer.rb +2 -2
- data/lib/ruhoh/ui/dashboard.rb +13 -0
- data/lib/ruhoh/ui/page_not_found.rb +3 -2
- data/lib/ruhoh/url_slug.rb +23 -9
- data/lib/ruhoh/version.rb +1 -1
- data/lib/ruhoh/views/master_view.rb +1 -1
- data/spec/lib/ruhoh/plugins/initializer_spec.rb +43 -0
- data/spec/lib/ruhoh/plugins/plugin_spec.rb +40 -0
- data/spec/spec_helper.rb +1 -0
- data/system/config.json +21 -0
- data/system/{dash/index.html → dashboard.html} +1 -1
- data/{lib/ruhoh/ui → system}/page_not_found.html +0 -0
- data/system/plugins/sprockets/compiler.rb +1 -0
- data/system/widgets/comments/disqus.html +1 -1
- metadata +34 -15
- data/lib/ruhoh/base/collection.rb +0 -284
- data/lib/ruhoh/base/compiler.rb +0 -67
- data/lib/ruhoh/base/model.rb +0 -161
- data/lib/ruhoh/base/model_view.rb +0 -129
- data/lib/ruhoh/base/watcher.rb +0 -25
- data/lib/ruhoh/resources/dash/collection.rb +0 -10
- data/lib/ruhoh/resources/dash/model.rb +0 -5
- data/lib/ruhoh/resources/dash/model_view.rb +0 -5
- 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.
|
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.
|
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.
|
8
|
-
@system_path = File.join(@ruhoh.
|
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
|
data/lib/ruhoh/routes.rb
CHANGED
@@ -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::
|
31
|
+
@ruhoh.collections.collection(r).include?(Ruhoh::Base::Routable) rescue false
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
data/lib/ruhoh/summarizer.rb
CHANGED
@@ -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
|
-
|
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
|
|
data/lib/ruhoh/url_slug.rb
CHANGED
@@ -20,15 +20,33 @@ class Ruhoh
|
|
20
20
|
|
21
21
|
# @return[String] the dynamic URL with token substitution.
|
22
22
|
def dynamic
|
23
|
-
|
24
|
-
|
25
|
-
|
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 =
|
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
|
data/lib/ruhoh/version.rb
CHANGED
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.expand_path '../../lib/ruhoh', __FILE__
|
data/system/config.json
ADDED
@@ -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
|
+
}
|
File without changes
|
@@ -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 = '
|
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.
|
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-
|
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/
|
182
|
-
- lib/ruhoh/base/
|
183
|
-
- lib/ruhoh/base/
|
184
|
-
- lib/ruhoh/base/
|
185
|
-
- lib/ruhoh/base/
|
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/
|
200
|
-
- lib/ruhoh/resources/
|
201
|
-
- lib/ruhoh/resources/
|
202
|
-
- lib/ruhoh/resources/
|
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/
|
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/
|
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:
|
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:
|
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
|