ro 1.4.6 → 4.2.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.
- checksums.yaml +6 -14
- data/Gemfile +2 -0
- data/Gemfile.lock +43 -0
- data/LICENSE +1 -0
- data/README.md +120 -112
- data/README.md.erb +159 -0
- data/Rakefile +129 -78
- data/bin/ro +241 -68
- data/lib/ro/_lib.rb +95 -0
- data/lib/ro/asset.rb +45 -0
- data/lib/ro/collection/list.rb +23 -0
- data/lib/ro/collection.rb +168 -0
- data/lib/ro/config.rb +68 -0
- data/lib/ro/error.rb +8 -0
- data/lib/ro/klass.rb +25 -0
- data/lib/ro/methods.rb +238 -0
- data/lib/ro/model.rb +83 -114
- data/lib/ro/node.rb +177 -360
- data/lib/ro/pagination.rb +7 -4
- data/lib/ro/path.rb +225 -0
- data/lib/ro/root.rb +52 -31
- data/lib/ro/script/builder.rb +221 -0
- data/lib/ro/script/console.rb +47 -0
- data/lib/ro/script/server.rb +76 -0
- data/lib/ro/script.rb +189 -0
- data/lib/ro/slug.rb +19 -18
- data/lib/ro/template/rouge_formatter.rb +42 -0
- data/lib/ro/template.rb +104 -50
- data/lib/ro.rb +85 -317
- data/public/api/ro/index-1.json +147 -0
- data/public/api/ro/index.json +137 -0
- data/public/api/ro/posts/first_post/index.json +52 -0
- data/public/api/ro/posts/index-1.json +145 -0
- data/public/api/ro/posts/index.json +135 -0
- data/public/api/ro/posts/second_post/index.json +51 -0
- data/public/api/ro/posts/third_post/index.json +51 -0
- data/public/ro/posts/first_post/assets/foo/bar/baz.jpg +0 -0
- data/public/ro/posts/first_post/assets/foo.jpg +0 -0
- data/public/ro/posts/first_post/assets/src/foo/bar.rb +3 -0
- data/public/ro/posts/first_post/attributes.yml +2 -0
- data/public/ro/posts/first_post/blurb.erb.md +7 -0
- data/public/ro/posts/first_post/body.md +16 -0
- data/public/ro/posts/first_post/testing.txt +3 -0
- data/public/ro/posts/second_post/assets/foo/bar/baz.jpg +0 -0
- data/public/ro/posts/second_post/assets/foo.jpg +0 -0
- data/public/ro/posts/second_post/assets/src/foo/bar.rb +3 -0
- data/public/ro/posts/second_post/attributes.yml +2 -0
- data/public/ro/posts/second_post/blurb.erb.md +5 -0
- data/public/ro/posts/second_post/body.md +16 -0
- data/public/ro/posts/third_post/assets/foo/bar/baz.jpg +0 -0
- data/public/ro/posts/third_post/assets/foo.jpg +0 -0
- data/public/ro/posts/third_post/assets/src/foo/bar.rb +3 -0
- data/public/ro/posts/third_post/attributes.yml +2 -0
- data/public/ro/posts/third_post/blurb.erb.md +5 -0
- data/public/ro/posts/third_post/body.md +16 -0
- data/ro.gemspec +89 -29
- metadata +106 -90
- data/TODO.md +0 -50
- data/lib/ro/blankslate.rb +0 -7
- data/lib/ro/cache.rb +0 -26
- data/lib/ro/git.rb +0 -374
- data/lib/ro/initializers/env.rb +0 -5
- data/lib/ro/initializers/tilt.rb +0 -104
- data/lib/ro/lock.rb +0 -53
- data/lib/ro/node/list.rb +0 -142
- data/notes/ara.txt +0 -215
data/lib/ro/node.rb
CHANGED
|
@@ -1,478 +1,295 @@
|
|
|
1
1
|
module Ro
|
|
2
2
|
class Node
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
fattr :loaded
|
|
7
|
-
fattr :fields
|
|
3
|
+
include Klass
|
|
4
|
+
|
|
5
|
+
attr_reader :path, :root
|
|
8
6
|
|
|
9
7
|
def initialize(path)
|
|
10
|
-
@path =
|
|
11
|
-
@
|
|
12
|
-
@
|
|
13
|
-
@type = File.basename(File.dirname(@path))
|
|
14
|
-
@root = Ro::Root.new(File.dirname(File.dirname(@path)))
|
|
15
|
-
@loaded = false
|
|
16
|
-
@loading = false
|
|
17
|
-
@attributes = Map.new
|
|
18
|
-
@fields = Map.new
|
|
8
|
+
@path = Path.for(path)
|
|
9
|
+
@root = Root.for(@path.parent.parent)
|
|
10
|
+
@attributes = :lazyload
|
|
19
11
|
end
|
|
20
12
|
|
|
21
|
-
def
|
|
22
|
-
@
|
|
13
|
+
def name
|
|
14
|
+
@path.name
|
|
23
15
|
end
|
|
24
16
|
|
|
25
|
-
def
|
|
26
|
-
|
|
17
|
+
def id
|
|
18
|
+
name
|
|
27
19
|
end
|
|
28
20
|
|
|
29
21
|
def type
|
|
30
|
-
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def _type
|
|
34
|
-
@type
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def path
|
|
38
|
-
attributes[:path] || @path
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def _path
|
|
42
|
-
@path
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def slug
|
|
46
|
-
attributes[:slug] || @slug
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def _slug
|
|
50
|
-
@slug
|
|
22
|
+
@path.parent.name
|
|
51
23
|
end
|
|
52
24
|
|
|
53
25
|
def identifier
|
|
54
|
-
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def hash
|
|
58
|
-
identifier.hash
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def ==(other)
|
|
62
|
-
attributes == other.attributes
|
|
26
|
+
File.join(type, id)
|
|
63
27
|
end
|
|
64
28
|
|
|
65
29
|
def inspect
|
|
66
30
|
identifier
|
|
67
31
|
end
|
|
68
32
|
|
|
69
|
-
def
|
|
70
|
-
|
|
33
|
+
def collection
|
|
34
|
+
@root.collection_for(type)
|
|
71
35
|
end
|
|
72
36
|
|
|
73
|
-
def
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def node
|
|
78
|
-
self
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def get(*args)
|
|
82
|
-
attributes.get(*args)
|
|
37
|
+
def attributes
|
|
38
|
+
load_attributes
|
|
39
|
+
@attributes
|
|
83
40
|
end
|
|
84
41
|
|
|
85
|
-
def
|
|
86
|
-
attributes
|
|
42
|
+
def load_attributes
|
|
43
|
+
load_attributes! if @attributes == :lazyload
|
|
87
44
|
end
|
|
88
45
|
|
|
89
|
-
def
|
|
90
|
-
|
|
91
|
-
end
|
|
46
|
+
def load_attributes!
|
|
47
|
+
@attributes = Map.new
|
|
92
48
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
49
|
+
_load_base_attributes
|
|
50
|
+
_load_asset_attributes
|
|
51
|
+
_load_meta_attributes
|
|
52
|
+
_load_file_attributes
|
|
96
53
|
|
|
97
|
-
|
|
98
|
-
Dir.glob("#{ asset_dir }/**/**").select{|entry| test(?f, entry)}
|
|
54
|
+
@attributes
|
|
99
55
|
end
|
|
100
56
|
|
|
101
|
-
def
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
Asset.new(name, :path => path, :url => url)
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def asset_urls
|
|
111
|
-
assets.map(&:url)
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def asset_for(*args, &block)
|
|
115
|
-
options = Map.options_for!(args)
|
|
116
|
-
|
|
117
|
-
path_info = Ro.relative_path_for(args)
|
|
118
|
-
|
|
119
|
-
path = File.join(@path.to_s, 'assets', path_info)
|
|
120
|
-
|
|
121
|
-
glob = path_info.gsub(/[_-]/, '[_-]')
|
|
122
|
-
|
|
123
|
-
globs =
|
|
124
|
-
[
|
|
125
|
-
File.join(@path.to_s, 'assets', "#{ glob }"),
|
|
126
|
-
File.join(@path.to_s, 'assets', "#{ glob }*"),
|
|
127
|
-
File.join(@path.to_s, 'assets', "**/#{ glob }*")
|
|
57
|
+
def _load_base_attributes
|
|
58
|
+
disallowed =
|
|
59
|
+
%w[
|
|
60
|
+
assets
|
|
61
|
+
_meta
|
|
128
62
|
]
|
|
129
63
|
|
|
130
|
-
|
|
64
|
+
glob =
|
|
65
|
+
"attributes.{yml,yaml,json}"
|
|
131
66
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
raise ArgumentError.new("no asset matching #{ globs.inspect }")
|
|
135
|
-
else
|
|
136
|
-
path = candidates.first
|
|
137
|
-
name = path.sub(asset_dir + "/", "")
|
|
138
|
-
path_info = path.gsub(/^#{ Regexp.escape(Ro.root) }/, '')
|
|
139
|
-
url = File.join(Ro.route, path_info)
|
|
140
|
-
end
|
|
67
|
+
@path.glob(glob) do |file|
|
|
68
|
+
attrs = _render(file)
|
|
141
69
|
|
|
142
|
-
|
|
143
|
-
|
|
70
|
+
disallowed.each do |key|
|
|
71
|
+
Ro.error!("#{ file } must not contain the key #{key.inspect}") if attrs.has_key?(key)
|
|
72
|
+
end
|
|
144
73
|
|
|
145
|
-
|
|
146
|
-
begin
|
|
147
|
-
asset_for(*args, &block)
|
|
148
|
-
rescue
|
|
149
|
-
nil
|
|
74
|
+
@attributes.update(attrs)
|
|
150
75
|
end
|
|
151
76
|
end
|
|
152
77
|
|
|
153
|
-
class Asset < ::String
|
|
154
|
-
fattr(:path)
|
|
155
|
-
fattr(:url)
|
|
156
|
-
|
|
157
|
-
def initialize(name, options = {})
|
|
158
|
-
super(name)
|
|
159
|
-
ensure
|
|
160
|
-
options = Map.for(options)
|
|
161
78
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
79
|
+
def _load_asset_attributes
|
|
80
|
+
{}.tap do |hash|
|
|
81
|
+
assets.each do |asset|
|
|
82
|
+
key = asset.name
|
|
83
|
+
value = { url: asset.url, path: asset.path.relative_to(@root), src: asset.src }
|
|
84
|
+
hash[key] = value
|
|
167
85
|
end
|
|
168
|
-
end
|
|
169
86
|
|
|
170
|
-
|
|
171
|
-
self
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
IMAGE_RE = %r/[.](jpg|jpeg|png|gif|tif|tiff)$/i
|
|
175
|
-
|
|
176
|
-
def image?
|
|
177
|
-
!!(self =~ IMAGE_RE)
|
|
87
|
+
@attributes.set(assets: hash)
|
|
178
88
|
end
|
|
89
|
+
end
|
|
179
90
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
91
|
+
def _load_meta_attributes
|
|
92
|
+
{}.tap do |hash|
|
|
93
|
+
hash.update(
|
|
94
|
+
identifier:,
|
|
95
|
+
type:,
|
|
96
|
+
id:,
|
|
97
|
+
urls:
|
|
98
|
+
)
|
|
185
99
|
|
|
186
|
-
|
|
187
|
-
File.basename(path.to_s)
|
|
100
|
+
@attributes.set(_meta: hash)
|
|
188
101
|
end
|
|
189
102
|
end
|
|
190
103
|
|
|
191
|
-
def
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
opts = Map.new
|
|
104
|
+
def _load_file_attributes
|
|
105
|
+
ignored = _ignored_files
|
|
195
106
|
|
|
196
|
-
|
|
107
|
+
@path.files.each do |file|
|
|
108
|
+
next if ignored.include?(file)
|
|
197
109
|
|
|
198
|
-
|
|
110
|
+
rel = file.relative_to(@path)
|
|
199
111
|
|
|
200
|
-
|
|
112
|
+
key = rel.parts
|
|
113
|
+
basename = key.pop
|
|
114
|
+
base = basename.split('.', 2).first
|
|
115
|
+
key.push(base)
|
|
201
116
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
opts[:_] = File.stat(asset.path).mtime.utc.to_i
|
|
205
|
-
else
|
|
206
|
-
opts[:_] = ts
|
|
117
|
+
if @attributes.has?(key)
|
|
118
|
+
raise Error.new("#{ @path } clobbers #{ key.inspect }!")
|
|
207
119
|
end
|
|
208
|
-
end
|
|
209
120
|
|
|
210
|
-
|
|
211
|
-
asset.url
|
|
212
|
-
else
|
|
213
|
-
query_string = Ro.query_string_for(opts)
|
|
214
|
-
"#{ asset.url }?#{ query_string }"
|
|
215
|
-
end
|
|
216
|
-
end
|
|
121
|
+
value = _render(file)
|
|
217
122
|
|
|
218
|
-
|
|
219
|
-
begin
|
|
220
|
-
url_for(*args, &block)
|
|
221
|
-
rescue
|
|
222
|
-
nil
|
|
123
|
+
@attributes.set(key => value)
|
|
223
124
|
end
|
|
224
125
|
end
|
|
225
126
|
|
|
226
|
-
def
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
127
|
+
def _ignored_files
|
|
128
|
+
ignored_files =
|
|
129
|
+
%w[
|
|
130
|
+
attributes.yml
|
|
131
|
+
attributes.yaml
|
|
132
|
+
attributes.json
|
|
133
|
+
./assets/**/**
|
|
134
|
+
].map do |glob|
|
|
135
|
+
@path.glob(glob).select(&:file?)
|
|
136
|
+
end
|
|
235
137
|
|
|
236
|
-
|
|
237
|
-
re = /^#{ Regexp.escape(Ro.root) }/
|
|
238
|
-
@path.to_s.gsub(re, '')
|
|
138
|
+
ignored_files.flatten
|
|
239
139
|
end
|
|
240
140
|
|
|
241
|
-
def
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
Ro.log "Ro::Node(#{ identifier })#method_missing(#{ method.inspect }, #{ args.inspect })"
|
|
245
|
-
|
|
246
|
-
key = method.to_s
|
|
141
|
+
def _render(file)
|
|
142
|
+
value = Ro.render(file, _render_context)
|
|
247
143
|
|
|
248
|
-
if
|
|
249
|
-
|
|
144
|
+
if value.is_a?(Ro::Template::HTML)
|
|
145
|
+
html = value
|
|
146
|
+
value = Ro.expand_asset_urls(html, self)
|
|
250
147
|
end
|
|
251
148
|
|
|
252
|
-
|
|
253
|
-
return(
|
|
254
|
-
if @attributes.has_key?(key)
|
|
255
|
-
@attributes[key]
|
|
256
|
-
else
|
|
257
|
-
super
|
|
258
|
-
end
|
|
259
|
-
)
|
|
260
|
-
end
|
|
149
|
+
value
|
|
261
150
|
end
|
|
262
151
|
|
|
263
|
-
def
|
|
264
|
-
|
|
152
|
+
def _render_context
|
|
153
|
+
to_hash.tap do |context|
|
|
154
|
+
context[:ro] ||= root
|
|
155
|
+
context[:collection] ||= collection
|
|
156
|
+
end
|
|
265
157
|
end
|
|
266
158
|
|
|
267
|
-
def
|
|
268
|
-
|
|
269
|
-
end
|
|
270
|
-
|
|
271
|
-
def instance_eval(*args, &block)
|
|
272
|
-
_load{ super }
|
|
159
|
+
def get(*args)
|
|
160
|
+
attributes.get(*args)
|
|
273
161
|
end
|
|
274
162
|
|
|
275
|
-
def
|
|
276
|
-
|
|
277
|
-
related = @attributes.get(:related) || Map.new
|
|
278
|
-
nodes = List.new(root)
|
|
279
|
-
list = root.nodes
|
|
280
|
-
which = Coerce.list_of_strings(args)
|
|
281
|
-
|
|
282
|
-
related.each do |relationship, value|
|
|
283
|
-
unless which.empty?
|
|
284
|
-
next unless which.include?(relationship.to_s)
|
|
285
|
-
end
|
|
286
|
-
|
|
287
|
-
type, names =
|
|
288
|
-
case value
|
|
289
|
-
when Hash
|
|
290
|
-
value.to_a.first
|
|
291
|
-
else
|
|
292
|
-
[relationship, value]
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
names = Coerce.list_of_strings(names)
|
|
296
|
-
|
|
297
|
-
names.each do |name|
|
|
298
|
-
identifier = "#{ type }/#{ name }"
|
|
299
|
-
node = list.index[identifier]
|
|
300
|
-
node._load{ nodes.add(node) }
|
|
301
|
-
end
|
|
302
|
-
end
|
|
303
|
-
|
|
304
|
-
case
|
|
305
|
-
when block.nil?
|
|
306
|
-
nodes
|
|
307
|
-
|
|
308
|
-
when block
|
|
309
|
-
nodes.where(&block)
|
|
310
|
-
end
|
|
311
|
-
}
|
|
163
|
+
def [](*args)
|
|
164
|
+
attributes.get(*args)
|
|
312
165
|
end
|
|
313
166
|
|
|
314
|
-
def
|
|
315
|
-
|
|
316
|
-
_load(&block)
|
|
167
|
+
def relative_path
|
|
168
|
+
path.relative_to(root)
|
|
317
169
|
end
|
|
318
170
|
|
|
319
|
-
def
|
|
320
|
-
|
|
171
|
+
def asset_dir
|
|
172
|
+
path.join('assets')
|
|
321
173
|
end
|
|
322
174
|
|
|
323
|
-
def
|
|
324
|
-
|
|
175
|
+
def asset_paths
|
|
176
|
+
asset_dir.select { |entry| entry.file? }.sort
|
|
325
177
|
end
|
|
326
178
|
|
|
327
|
-
def
|
|
328
|
-
|
|
329
|
-
if @loading
|
|
330
|
-
return(block ? block.call : :loading)
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
@loading = true
|
|
334
|
-
@loaded = _load_from_cache_or_disk
|
|
335
|
-
@loading = false
|
|
336
|
-
end
|
|
337
|
-
|
|
338
|
-
block ? block.call : @loaded
|
|
179
|
+
def assets
|
|
180
|
+
asset_paths.map { |path| Asset.for(path, node: self) }
|
|
339
181
|
end
|
|
340
182
|
|
|
341
|
-
def
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
cached = Ro.cache.read(cache_key)
|
|
183
|
+
def asset_urls
|
|
184
|
+
assets.map(&:url)
|
|
185
|
+
end
|
|
345
186
|
|
|
346
|
-
|
|
347
|
-
|
|
187
|
+
def asset_for(*args)
|
|
188
|
+
options = Map.options_for!(args)
|
|
348
189
|
|
|
349
|
-
|
|
190
|
+
path_info = Path.relative(args)
|
|
350
191
|
|
|
351
|
-
|
|
352
|
-
else
|
|
353
|
-
Ro.log "loading #{ identifier } from disk"
|
|
192
|
+
path = @path.join('assets', path_info)
|
|
354
193
|
|
|
355
|
-
|
|
194
|
+
glob = path_info.gsub(/[_-]/, '[_-]')
|
|
356
195
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
196
|
+
globs =
|
|
197
|
+
[
|
|
198
|
+
@path.call('assets', "#{glob}"),
|
|
199
|
+
@path.call('assets', "#{glob}*"),
|
|
200
|
+
@path.call('assets', "**/#{glob}*")
|
|
201
|
+
]
|
|
361
202
|
|
|
362
|
-
|
|
203
|
+
candidates = globs.map { |glob| Dir.glob(glob, ::File::FNM_CASEFOLD) }.flatten.compact.uniq.sort
|
|
363
204
|
|
|
364
|
-
|
|
205
|
+
case candidates.size
|
|
206
|
+
when 0
|
|
207
|
+
raise ArgumentError, "no asset matching #{globs.inspect}"
|
|
208
|
+
else
|
|
209
|
+
path = candidates.last
|
|
365
210
|
end
|
|
366
|
-
end
|
|
367
|
-
|
|
368
|
-
def _load_attributes_yml
|
|
369
|
-
if test(?s, _attributes_yml)
|
|
370
|
-
buf = IO.binread(_attributes_yml)
|
|
371
|
-
data = YAML.load(buf)
|
|
372
|
-
data = data.is_a?(Hash) ? data : {'_' => data}
|
|
373
|
-
|
|
374
|
-
@attributes.update(data)
|
|
375
|
-
|
|
376
|
-
%w( assets ).each do |key|
|
|
377
|
-
raise ArgumentError.new("attributes.yml may not contain the key '#{ key }'") if @attributes.has_key?(key)
|
|
378
|
-
end
|
|
379
211
|
|
|
380
|
-
|
|
381
|
-
end
|
|
212
|
+
Asset.for(path, node: self)
|
|
382
213
|
end
|
|
383
214
|
|
|
384
|
-
def
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
next if test(?d, path)
|
|
390
|
-
|
|
391
|
-
basename = File.basename(path)
|
|
392
|
-
next if basename == 'attributes.yml'
|
|
393
|
-
|
|
394
|
-
relative_path = Ro.relative_path(path, :to => @path)
|
|
395
|
-
next if relative_path =~ /^assets\//
|
|
215
|
+
def asset_for?(*args, &block)
|
|
216
|
+
asset_for(*args, &block)
|
|
217
|
+
rescue StandardError
|
|
218
|
+
nil
|
|
219
|
+
end
|
|
396
220
|
|
|
397
|
-
|
|
221
|
+
def url_for(relative_path, options = {})
|
|
222
|
+
raise ArgumentError, relative_path if Path.absolute?(relative_path)
|
|
398
223
|
|
|
399
|
-
|
|
400
|
-
|
|
224
|
+
fullpath = Path.for(path, relative_path).expand
|
|
225
|
+
raise ArgumentError, "#{relative_path.inspect} -- DOES NOT EXIST" unless fullpath.exist?
|
|
401
226
|
|
|
402
|
-
|
|
403
|
-
end
|
|
227
|
+
Ro.url_for(self.relative_path, relative_path, options)
|
|
404
228
|
end
|
|
405
229
|
|
|
406
|
-
def
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
Dir.glob(glob) do |path|
|
|
411
|
-
next if test(?d, path)
|
|
412
|
-
|
|
413
|
-
basename = File.basename(path)
|
|
414
|
-
key, ext = basename.split('.', 2)
|
|
230
|
+
def src_for(*args)
|
|
231
|
+
key = Path.relative(:assets, :src, args).split('/')
|
|
232
|
+
get(key)
|
|
233
|
+
end
|
|
415
234
|
|
|
416
|
-
|
|
235
|
+
def method_missing(method, *args, &block)
|
|
236
|
+
key = method.to_s
|
|
417
237
|
|
|
418
|
-
|
|
419
|
-
|
|
238
|
+
if attributes.has_key?(key)
|
|
239
|
+
attributes[key]
|
|
240
|
+
else
|
|
241
|
+
super
|
|
420
242
|
end
|
|
421
243
|
end
|
|
422
244
|
|
|
423
|
-
def
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
Dir.glob(glob) do |path|
|
|
428
|
-
next if test(?d, path)
|
|
429
|
-
|
|
430
|
-
relative_path = Ro.relative_path(path, :to => "#{ @path }/assets")
|
|
431
|
-
|
|
432
|
-
url = url_for(relative_path)
|
|
433
|
-
key = relative_path.split('/')
|
|
434
|
-
|
|
435
|
-
key.unshift('urls')
|
|
245
|
+
def to_hash
|
|
246
|
+
attributes.to_hash
|
|
247
|
+
end
|
|
436
248
|
|
|
437
|
-
|
|
438
|
-
|
|
249
|
+
def to_s(...)
|
|
250
|
+
to_json(...)
|
|
439
251
|
end
|
|
440
252
|
|
|
441
|
-
def
|
|
442
|
-
|
|
253
|
+
def to_json(...)
|
|
254
|
+
JSON.pretty_generate(to_hash, ...)
|
|
443
255
|
end
|
|
444
256
|
|
|
445
|
-
def
|
|
446
|
-
|
|
257
|
+
def as_json(...)
|
|
258
|
+
to_hash.as_json(...)
|
|
259
|
+
end
|
|
447
260
|
|
|
448
|
-
|
|
261
|
+
def to_yaml(...)
|
|
262
|
+
to_hash.to_yaml(...)
|
|
263
|
+
end
|
|
449
264
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
begin
|
|
453
|
-
File.stat(entry)
|
|
454
|
-
rescue
|
|
455
|
-
next
|
|
456
|
-
end
|
|
265
|
+
def _mapify(data)
|
|
266
|
+
converted = 'this_recursively_converts_nested_hashes_into_maps'
|
|
457
267
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
entries.push([relative_path, timestamp.iso8601(2)])
|
|
461
|
-
end
|
|
268
|
+
Map.for(converted => data)[converted]
|
|
269
|
+
end
|
|
462
270
|
|
|
463
|
-
|
|
271
|
+
def files
|
|
272
|
+
path.glob('**/**').select { |entry| entry.file? }.sort
|
|
273
|
+
end
|
|
464
274
|
|
|
465
|
-
|
|
275
|
+
def urls
|
|
276
|
+
files.map { |file| url_for(file.relative_to(@path)) }.sort
|
|
277
|
+
end
|
|
466
278
|
|
|
467
|
-
|
|
279
|
+
def <=>(other)
|
|
280
|
+
sort_key <=> other.sort_key
|
|
468
281
|
end
|
|
469
282
|
|
|
470
|
-
def
|
|
471
|
-
|
|
283
|
+
def sort_key
|
|
284
|
+
default_sort_key
|
|
472
285
|
end
|
|
473
286
|
|
|
474
|
-
def
|
|
475
|
-
|
|
287
|
+
def default_sort_key
|
|
288
|
+
position = (attributes[:position] ? Float(attributes[:position]) : 0.0)
|
|
289
|
+
published_at = (attributes[:published_at] ? Time.parse(attributes[:published_at].to_s) : Time.at(0)).utc.iso8601
|
|
290
|
+
created_at = (attributes[:created_at] ? Time.parse(attributes[:created_at].to_s) : Time.at(0)).utc.iso8601
|
|
291
|
+
|
|
292
|
+
[position, published_at, created_at, name]
|
|
476
293
|
end
|
|
477
294
|
end
|
|
478
295
|
end
|
data/lib/ro/pagination.rb
CHANGED
|
@@ -8,9 +8,9 @@ module Ro
|
|
|
8
8
|
|
|
9
9
|
page = [page.abs, 1].max
|
|
10
10
|
per = [per.abs, 1].max
|
|
11
|
-
|
|
11
|
+
d
|
|
12
12
|
offset = (page - 1) * per
|
|
13
|
-
length = per
|
|
13
|
+
length = per
|
|
14
14
|
|
|
15
15
|
slice = dup.slice(offset, length)
|
|
16
16
|
slice.page = page
|
|
@@ -23,12 +23,13 @@ module Ro
|
|
|
23
23
|
@page = page
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def page(*
|
|
26
|
+
def page(*_args)
|
|
27
|
+
paginate unless @page
|
|
27
28
|
@page
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
def current_page
|
|
31
|
-
|
|
32
|
+
page
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
def per=(per)
|
|
@@ -36,6 +37,7 @@ module Ro
|
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
def per
|
|
40
|
+
paginate unless @per
|
|
39
41
|
@per
|
|
40
42
|
end
|
|
41
43
|
|
|
@@ -44,6 +46,7 @@ module Ro
|
|
|
44
46
|
end
|
|
45
47
|
|
|
46
48
|
def num_pages
|
|
49
|
+
paginate unless @num_pages
|
|
47
50
|
@num_pages
|
|
48
51
|
end
|
|
49
52
|
|