ro 1.4.6 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. checksums.yaml +6 -14
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +64 -0
  4. data/LICENSE +1 -0
  5. data/README.md +276 -105
  6. data/README.md.erb +159 -0
  7. data/Rakefile +129 -78
  8. data/bin/ro +241 -68
  9. data/lib/ro/_lib.rb +107 -0
  10. data/lib/ro/asset.rb +55 -0
  11. data/lib/ro/collection/list.rb +23 -0
  12. data/lib/ro/collection.rb +211 -0
  13. data/lib/ro/config.rb +72 -0
  14. data/lib/ro/error.rb +11 -0
  15. data/lib/ro/html.rb +23 -0
  16. data/lib/ro/html_safe.rb +143 -0
  17. data/lib/ro/klass.rb +25 -0
  18. data/lib/ro/methods.rb +295 -0
  19. data/lib/ro/model.rb +83 -114
  20. data/lib/ro/node.rb +209 -349
  21. data/lib/ro/pagination.rb +7 -4
  22. data/lib/ro/path.rb +229 -0
  23. data/lib/ro/root.rb +52 -31
  24. data/lib/ro/script/builder.rb +221 -0
  25. data/lib/ro/script/console.rb +47 -0
  26. data/lib/ro/script/server.rb +76 -0
  27. data/lib/ro/script.rb +189 -0
  28. data/lib/ro/slug.rb +19 -18
  29. data/lib/ro/template/rouge_formatter.rb +42 -0
  30. data/lib/ro/template.rb +145 -51
  31. data/lib/ro/text.rb +120 -0
  32. data/lib/ro.rb +89 -317
  33. data/public/api/ro/index-1.json +1065 -0
  34. data/public/api/ro/index.json +1055 -0
  35. data/public/api/ro/nerd/fastest-possible-embeddings/index.json +90 -0
  36. data/public/api/ro/nerd/ima/index.json +49 -0
  37. data/public/api/ro/nerd/index/index.json +74 -0
  38. data/public/api/ro/nerd/index-1.json +204 -0
  39. data/public/api/ro/nerd/index.json +194 -0
  40. data/public/api/ro/pages/about/index.json +60 -0
  41. data/public/api/ro/pages/contact/index.json +50 -0
  42. data/public/api/ro/pages/cv/index.json +49 -0
  43. data/public/api/ro/pages/disco/index.json +117 -0
  44. data/public/api/ro/pages/index/index.json +30 -0
  45. data/public/api/ro/pages/index-1.json +366 -0
  46. data/public/api/ro/pages/index.json +356 -0
  47. data/public/api/ro/pages/jess/index.json +62 -0
  48. data/public/api/ro/pages/now/index.json +43 -0
  49. data/public/api/ro/posts/almost-died-in-an-ice-cave/index.json +265 -0
  50. data/public/api/ro/posts/facebook-and-global-extremism/index.json +90 -0
  51. data/public/api/ro/posts/index-1.json +527 -0
  52. data/public/api/ro/posts/index.json +517 -0
  53. data/public/api/ro/posts/lemmings-considered-harmful/index.json +49 -0
  54. data/public/api/ro/posts/lost-in-the-desert/index.json +49 -0
  55. data/public/api/ro/posts/mission/index.json +49 -0
  56. data/public/api/ro/posts/return-your-laptop/index.json +61 -0
  57. data/public/ro/nerd/fastest-possible-embeddings/assets/giraffe.jpeg +0 -0
  58. data/public/ro/nerd/fastest-possible-embeddings/assets/let-me-in.jpg +0 -0
  59. data/public/ro/nerd/fastest-possible-embeddings/assets/src/fastembed.js +70 -0
  60. data/public/ro/nerd/fastest-possible-embeddings/assets/src/fastembed.rs +68 -0
  61. data/public/ro/nerd/fastest-possible-embeddings/assets/terminal.jpg +0 -0
  62. data/public/ro/nerd/fastest-possible-embeddings/attributes.yml +7 -0
  63. data/public/ro/nerd/fastest-possible-embeddings/body.md +266 -0
  64. data/public/ro/nerd/ima/assets/og.jpeg +0 -0
  65. data/public/ro/nerd/ima/attributes.yml +8 -0
  66. data/public/ro/nerd/ima/body.md +22 -0
  67. data/public/ro/nerd/index/assets/giraffe.jpeg +0 -0
  68. data/public/ro/nerd/index/assets/let-me-in.jpg +0 -0
  69. data/public/ro/nerd/index/assets/terminal.jpg +0 -0
  70. data/public/ro/nerd/index/attributes.yml +7 -0
  71. data/public/ro/nerd/index/body.md +130 -0
  72. data/public/ro/pages/about/assets/og.jpeg +0 -0
  73. data/public/ro/pages/about/assets/speak-english-pulp-fiction.gif +0 -0
  74. data/public/ro/pages/about/body.md +40 -0
  75. data/public/ro/pages/contact/assets/giraffe.jpeg +0 -0
  76. data/public/ro/pages/contact/attributes.yml +7 -0
  77. data/public/ro/pages/contact/body.md +9 -0
  78. data/public/ro/pages/cv/assets/ara.jpg +0 -0
  79. data/public/ro/pages/cv/attributes.yml +6 -0
  80. data/public/ro/pages/cv/body.md +122 -0
  81. data/public/ro/pages/disco/assets/disco.jpg +0 -0
  82. data/public/ro/pages/disco/assets/disco.png +0 -0
  83. data/public/ro/pages/disco/assets/speak-english-pulp-fiction.gif +0 -0
  84. data/public/ro/pages/disco/assets/src/environment.md +2354 -0
  85. data/public/ro/pages/disco/assets/src/fortune-500.md +2518 -0
  86. data/public/ro/pages/disco/assets/src/greed.md +2703 -0
  87. data/public/ro/pages/disco/assets/src/up-at-night.md +2337 -0
  88. data/public/ro/pages/disco/attributes.yml +9 -0
  89. data/public/ro/pages/disco/body.md +99 -0
  90. data/public/ro/pages/disco/samples/environment.md +2354 -0
  91. data/public/ro/pages/disco/samples/fortune-500.md +2518 -0
  92. data/public/ro/pages/disco/samples/greed.md +2703 -0
  93. data/public/ro/pages/disco/samples/up-at-night.md +2337 -0
  94. data/public/ro/pages/index/attributes.yml +1 -0
  95. data/public/ro/pages/index/body.md +15 -0
  96. data/public/ro/pages/jess/assets/og.jpg +0 -0
  97. data/public/ro/pages/jess/assets/speak-english-pulp-fiction.gif +0 -0
  98. data/public/ro/pages/jess/attributes.yml +7 -0
  99. data/public/ro/pages/jess/body.md +3 -0
  100. data/public/ro/pages/now/assets/speak-english-pulp-fiction.gif +0 -0
  101. data/public/ro/pages/now/attributes.yml +1 -0
  102. data/public/ro/pages/now/body.md +24 -0
  103. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image1.png +0 -0
  104. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image10.png +0 -0
  105. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image11.png +0 -0
  106. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image12.png +0 -0
  107. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image13.png +0 -0
  108. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image14.png +0 -0
  109. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image15.png +0 -0
  110. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image2.png +0 -0
  111. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image3.png +0 -0
  112. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image4.png +0 -0
  113. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image5.png +0 -0
  114. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image6.png +0 -0
  115. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image7.png +0 -0
  116. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image8.png +0 -0
  117. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image9.png +0 -0
  118. data/public/ro/posts/almost-died-in-an-ice-cave/assets/josh-pointing.jpg +0 -0
  119. data/public/ro/posts/almost-died-in-an-ice-cave/assets/levi-rawr.png +0 -0
  120. data/public/ro/posts/almost-died-in-an-ice-cave/assets/og.jpg +0 -0
  121. data/public/ro/posts/almost-died-in-an-ice-cave/assets/purple-heart.jpg +0 -0
  122. data/public/ro/posts/almost-died-in-an-ice-cave/attributes.yml +6 -0
  123. data/public/ro/posts/almost-died-in-an-ice-cave/body.md +419 -0
  124. data/public/ro/posts/facebook-and-global-extremism/assets/background.html +125 -0
  125. data/public/ro/posts/facebook-and-global-extremism/assets/background.md +95 -0
  126. data/public/ro/posts/facebook-and-global-extremism/assets/og.jpg +0 -0
  127. data/public/ro/posts/facebook-and-global-extremism/assets/prompt.txt +122 -0
  128. data/public/ro/posts/facebook-and-global-extremism/assets/results.md +183 -0
  129. data/public/ro/posts/facebook-and-global-extremism/assets/survey.txt +190 -0
  130. data/public/ro/posts/facebook-and-global-extremism/attributes.yml +7 -0
  131. data/public/ro/posts/facebook-and-global-extremism/body.md +393 -0
  132. data/public/ro/posts/lemmings-considered-harmful/assets/lemming.jpeg +0 -0
  133. data/public/ro/posts/lemmings-considered-harmful/attributes.yml +6 -0
  134. data/public/ro/posts/lemmings-considered-harmful/body.md +43 -0
  135. data/public/ro/posts/lost-in-the-desert/assets/og.jpg +0 -0
  136. data/public/ro/posts/lost-in-the-desert/attributes.yml +6 -0
  137. data/public/ro/posts/lost-in-the-desert/body.md +7 -0
  138. data/public/ro/posts/mission/assets/og.jpg +0 -0
  139. data/public/ro/posts/mission/attributes.yml +6 -0
  140. data/public/ro/posts/mission/body.md +4 -0
  141. data/public/ro/posts/return-your-laptop/assets/og.jpg +0 -0
  142. data/public/ro/posts/return-your-laptop/assets/return-your-laptop.png +0 -0
  143. data/public/ro/posts/return-your-laptop/attributes.yml +6 -0
  144. data/public/ro/posts/return-your-laptop/body.md +58 -0
  145. data/ro.gemspec +217 -28
  146. data/scripts/speedtest.rb +324 -0
  147. data/tmp/gem-details.oe +0 -0
  148. metadata +214 -74
  149. data/TODO.md +0 -50
  150. data/lib/ro/blankslate.rb +0 -7
  151. data/lib/ro/cache.rb +0 -26
  152. data/lib/ro/git.rb +0 -374
  153. data/lib/ro/initializers/env.rb +0 -5
  154. data/lib/ro/initializers/tilt.rb +0 -104
  155. data/lib/ro/lock.rb +0 -53
  156. data/lib/ro/node/list.rb +0 -142
  157. data/notes/ara.txt +0 -215
data/bin/ro CHANGED
@@ -1,102 +1,275 @@
1
1
  #! /usr/bin/env ruby
2
+ # encoding: utf-8
2
3
 
3
- Main {
4
+ Ro.script do
5
+ help <<~____
6
+ NAME
7
+ ----
8
+ ro
9
+
10
+ SYNOPSIS
11
+ --------
12
+ * boot an interactive r.e.p.l. over yer ro data
13
+ * build a json api for your ro data
14
+ * run a local dev server for your ro data
4
15
 
5
- argument('root'){
6
- optional
7
- }
16
+ TL;DR;
17
+ ------
18
+ # boot a console for the ro a ./public/ro (the default)
19
+ #
20
+ ~> ro console
8
21
 
9
- def run
22
+ # build a static API into ./public/api/ro (the default)
23
+ #
24
+ ~> ro build
25
+
26
+ # keep building that static a.p.i when any file changes
27
+ #
28
+ ~> ro watch
29
+
30
+ # run a local http server that re-builds that static a.p.i on change
31
+ #
32
+ ~> ro server
33
+
34
+ # show defaults
35
+ #
36
+ ~> ro defaults
37
+
38
+ # show env
39
+ #
40
+ ~> ro env
41
+
42
+ # show config
43
+ #
44
+ ~> ro config
45
+
46
+ ENV
47
+ ---
48
+ - all sub commands can be affect by the following env vars
49
+ - 12 factor ftw
50
+
51
+ - RO_ROOT
52
+ - the root directory of your ro data
53
+ - RO_BUILD
54
+ - the build directory for your ro data api
55
+ - RO_URL
56
+ - the url prefix where your ro data will be found on the interwebs
57
+ - you may use a relative or absolute url
58
+ - please make sure this will resolve
59
+ - RO_PAGE_SIZE
60
+ - the built a.p.i.'s page size
61
+ - RO_LOG
62
+ - log on, or log off
63
+ - RO_DEBUG
64
+ - debug or no debug
65
+ - RO_PORT
66
+ - le port to to serve on
67
+
68
+ ARGV
69
+ ----
70
+ - for *all* sub commands
71
+ - you may also specifiy RO_ROOT as the 1'st argument
72
+ - you may also specifiy RO_BUILD as the 2'nd argument
73
+ - you may specify env vars in argv as 'RO_XXX=YYY' pairs, for example:
74
+ ~ `ro console RO_ROOT=./public/ro`
75
+ - or
76
+ ~ `ro console ro_root=./public/ro`
77
+
78
+ API
79
+ - the a.p.i is trivially simple, examine the output.
80
+ - if you can't figure out how to use it your probably should not.
81
+ ____
82
+
83
+ run do
10
84
  help!
11
85
  end
12
86
 
13
- mode(:console){
14
- def run
15
- if params['root'].given?
16
- Ro.root = params['root'].value
17
- else
18
- if ENV['RO_ROOT']
19
- Ro.root = ENV['RO_ROOT']
20
- else
21
- Ro.root = './ro'
22
- end
23
- end
87
+ run(:console) do
88
+ setup!(:root)
24
89
 
25
- basename = File.basename(Ro.root)
90
+ console!
91
+ end
26
92
 
27
- ARGV.clear
28
- require 'irb'
93
+ run(:build) do
94
+ setup!(:root, :build)
29
95
 
30
- Kernel.module_eval do
31
- def reload!
32
- Object.send(:remove_const, :Ro)
33
- load "#{ $libdir }/ro.rb"
34
- "#{ $libdir }/ro.rb"
35
- end
36
- end
96
+ build!
97
+ end
37
98
 
38
- $HACK = IRB.method(:load_modules)
99
+ run(:watch) do
100
+ setup!(:root, :build)
39
101
 
40
- def IRB.load_modules
41
- $HACK.call()
102
+ watch!
103
+ end
104
+
105
+ run(:server) do
106
+ setup!(:root, :build)
42
107
 
43
- basename = File.basename(Ro.root)
108
+ server!
109
+ end
44
110
 
45
- IRB.conf[:PROMPT][:RO] = {
46
- :PROMPT_I=>"Ro(./#{ basename }):%03n:%i> ",
47
- :PROMPT_N=>"Ro(./#{ basename }):%03n:%i> ",
48
- :PROMPT_S=>"Ro(./#{ basename }):%03n:%i%l ",
49
- :PROMPT_C=>"Ro(./#{ basename }):%03n:%i* ",
50
- :RETURN=>"=> %s\n"
51
- }
111
+ run(:defaults) do
112
+ setup!
52
113
 
53
- IRB.conf[:PROMPT_MODE] = :RO
54
- IRB.conf[:AUTO_INDENT] = true
55
- end
114
+ defaults!
115
+ end
116
+
117
+ run(:env) do
118
+ setup!
119
+
120
+ env!
121
+ end
122
+
123
+ run(:config) do
124
+ setup!
125
+
126
+ config!
127
+ end
128
+
129
+ run(:site) do
130
+ site!
131
+ end
56
132
 
133
+ def setup!(*which)
134
+ setup_env!
57
135
 
58
- ::IRB.start
136
+ parse_argv!(*which)
137
+
138
+ validate!
139
+
140
+ if which.include?(:ro)
141
+ @ro = Ro.root
59
142
  end
143
+ end
60
144
 
61
- =begin
62
- module Console
63
- def reload!
64
- Object.send(:remove_const, :Ro)
65
- load "#{ $libdir }/ro.rb"
66
- "#{ $libdir }/ro.rb"
145
+ attr_reader :ro
146
+
147
+ def parse_argv!(*which)
148
+ if which.include?(:root)
149
+ if argv.size > 0
150
+ Ro.config.root = argv.shift
67
151
  end
68
152
  end
69
- =end
70
153
 
71
- class Console < Ro::BlankSlate
72
- def initialize(nodes)
73
- @nodes = nodes
154
+ if which.include?(:build)
155
+ if argv.size > 0
156
+ Ro.config.build = argv.shift
74
157
  end
158
+ end
159
+ end
75
160
 
76
- def binding
77
- Kernel.binding
78
- end
161
+ def setup_env!
162
+ argv.dup.each_with_index do |arg, i|
163
+ key, val = arg.split('=', 2)
79
164
 
80
- def reload!
81
- Object.send(:remove_const, :Ro)
82
- load "#{ $libdir }/ro.rb"
83
- "#{ $libdir }/ro.rb"
84
- end
165
+ if key && val
166
+ ENV[key.upcase] = val
85
167
 
86
- def method_missing(method, *args, &block)
87
- @nodes.send(method, *args, &block)
168
+ argv.delete_at(i)
88
169
  end
89
170
  end
90
- }
91
171
 
92
- }
172
+ if ENV['PORT']
173
+ Ro.config.port = ENV['PORT']
174
+ end
175
+ end
176
+
177
+ def validate!
178
+ abort("Ro.root = #{ Ro.config.root.expand } is not a directory") unless test(?d, Ro.config.root)
179
+ abort("Ro.root = #{ Ro.config.root.expand } is empty") unless test(?s, Ro.config.root)
180
+ end
181
+
182
+ def console!
183
+ require "#{$libdir}/ro/script/console.rb"
184
+
185
+ Ro::Script::Console.run!(script: self)
186
+ end
187
+
188
+ def build!
189
+ require "#{$libdir}/ro/script/builder.rb"
190
+
191
+ Ro::Script::Builder.run!(script: self)
192
+ end
193
+
194
+ def server!
195
+ require "#{$libdir}/ro/script/server.rb"
196
+
197
+ Ro::Script::Server.run!(script: self)
198
+ end
199
+
200
+ def watch!
201
+ watch(Ro.config.root) { build! }
202
+ end
203
+
204
+ def watch(directory, &block)
205
+ require 'ak47'
206
+
207
+ def File.exists?(...) # monkey patch for Ak47 ;-/
208
+ File.exist?(...)
209
+ end
210
+
211
+ Ak47(watch_dirs: directory) do
212
+ block.call
213
+ end
214
+ end
215
+
216
+ def show(hash)
217
+ puts JSON.parse(hash.to_json).to_yaml
218
+ end
219
+
220
+ def defaults!
221
+ show Ro.defaults
222
+ end
223
+
224
+ def env!
225
+ show Ro.env
226
+ end
227
+
228
+ def config!
229
+ show Ro.config
230
+ end
231
+
232
+ def site!
233
+ document_root = Ro::Path.for(argv[0] || './public')
234
+
235
+ files = document_root.files.sort
236
+ hrefs = files.map{|file| file.relative_to(document_root).relative}
237
+ anchors = hrefs.map{|href| "<a href='./#{ href }' target='_blank'>./#{ href }</a>"}
238
+ lis = anchors.map{|anchor| "<li>#{ anchor }</li>"}
239
+
240
+ html = <<-____
241
+ <html>
242
+ <body style='padding:2em;'>
243
+ <br><br>
244
+ <strong>tl;dr;</strong>
245
+ <br><br>
246
+ <em>
247
+ see <a href="#{ Ro.repo }">#{ Ro.repo }</a> for moar deets
248
+ </em>
249
+ <br><br>
250
+ <hr><hr>
251
+ <ul>
252
+ #{ lis.join("\n") }
253
+ </ul>
254
+ </body>
255
+ </html>
256
+ ____
257
+
258
+ index_html = document_root.join('index.html')
259
+ index_html.binwrite(html)
260
+ puts index_html
261
+ end
262
+ end
93
263
 
94
264
  BEGIN {
95
- require 'main'
265
+ $stdout.sync = true
266
+ $stderr.sync = true
96
267
 
97
- $bindir = File.dirname(__FILE__)
98
- $libdir = File.expand_path("#{ $bindir }/../lib/")
268
+ $script = File.expand_path(__FILE__)
269
+ $bindir = File.dirname($script)
270
+ $root = File.dirname($bindir)
271
+ $libdir = File.join($root, 'lib')
99
272
 
100
- require "#{ $libdir }/ro.rb"
273
+ require "#{$libdir}/ro"
274
+ require "#{$libdir}/ro/script.rb"
101
275
  }
102
-
data/lib/ro/_lib.rb ADDED
@@ -0,0 +1,107 @@
1
+ module Ro
2
+ VERSION = '4.4.0' unless defined?(VERSION)
3
+
4
+ class << self
5
+ def version
6
+ VERSION
7
+ end
8
+
9
+ def repo
10
+ 'https://github.com/ahoward/ro'
11
+ end
12
+
13
+ def summary
14
+ <<~____
15
+ all your content in github, as god intended
16
+ ____
17
+ end
18
+
19
+ def description
20
+ <<~____
21
+ the worlds tiniest, bestest, most minmialist headless cms - powered by github
22
+
23
+ ro is a minimalist toolkit for managing heterogeneous collections of rich web
24
+ content on github, and providing both programatic and api access to it with zero
25
+ heavy lifting
26
+ ____
27
+ end
28
+
29
+ def libs
30
+ %w[
31
+ fileutils pathname yaml json logger erb cgi uri time date thread securerandom
32
+ ]
33
+ end
34
+
35
+ def dependencies
36
+ {
37
+ 'map' =>
38
+ ['map', '~> 6.6', '>= 6.6.0'],
39
+
40
+ 'kramdown' =>
41
+ ['kramdown', '~> 2.4', ' >= 2.4.0'],
42
+
43
+ 'kramdown-parser-gfm' =>
44
+ ['kramdown-parser-gfm', '~> 1.1', ' >= 1.1.0'],
45
+
46
+ 'rouge' =>
47
+ ['rouge', '~> 4.1', ' >= 4.1.1'],
48
+
49
+ 'front_matter_parser' =>
50
+ ['front_matter_parser', '~> 1.0'],
51
+
52
+ 'rinku' =>
53
+ ['rinku', '~> 2.0'],
54
+
55
+ #'ak47' =>
56
+ #['ak47', '~> 0.2'],
57
+
58
+ #'webrick' =>
59
+ #['webrick', '~> 1.9.1'],
60
+
61
+ 'image_size' =>
62
+ ['image_size', '~> 3.4'],
63
+
64
+ 'nokogiri' =>
65
+ ['nokogiri', '~> 1'],
66
+ }
67
+ end
68
+
69
+ def libdir(*args, &block)
70
+ @libdir ||= File.dirname(File.expand_path(__FILE__))
71
+ args.empty? ? @libdir : File.join(@libdir, *args)
72
+ ensure
73
+ if block
74
+ begin
75
+ $LOAD_PATH.unshift(@libdir)
76
+ block.call
77
+ ensure
78
+ $LOAD_PATH.shift
79
+ end
80
+ end
81
+ end
82
+
83
+ def load(*libs)
84
+ libs = libs.join(' ').scan(/[^\s+]+/)
85
+ libdir { libs.each { |lib| Kernel.load(lib) } }
86
+ end
87
+
88
+ def load_dependencies!
89
+ libs.each do |lib|
90
+ require lib
91
+ end
92
+
93
+ begin
94
+ require 'rubygems'
95
+ rescue LoadError
96
+ nil
97
+ end
98
+
99
+ has_rubygems = defined?(gem)
100
+
101
+ dependencies.each do |lib, dependency|
102
+ gem(*dependency) if has_rubygems
103
+ require(lib)
104
+ end
105
+ end
106
+ end
107
+ end
data/lib/ro/asset.rb ADDED
@@ -0,0 +1,55 @@
1
+ module Ro
2
+ class Asset < ::String
3
+ include Klass
4
+
5
+ attr_reader :path, :node, :relative_path, :name, :url
6
+
7
+ def initialize(arg, *args)
8
+ options = args.last.is_a?(Hash) ? args.pop : {}
9
+
10
+ @path = Path.for(arg, *args)
11
+
12
+ @node = options.fetch(:node) { Node.for(@path.split('/assets/').first) }
13
+
14
+ @relative_path = @path.relative_to(@node.path)
15
+
16
+ @name = @relative_path
17
+
18
+ @url = @node.url_for(@relative_path)
19
+
20
+ super(@path)
21
+ end
22
+
23
+ def is_img?
24
+ @path.file? && Ro.is_image?(@path.basename)
25
+ end
26
+
27
+ alias is_img is_img?
28
+
29
+ def img
30
+ return unless is_img?
31
+ Ro.image_info(path.to_s)
32
+ end
33
+
34
+ def is_src?
35
+ key = relative_path.parts
36
+ subdir = key.size > 2 ? key[1] : nil
37
+ !!(subdir == 'src')
38
+ end
39
+
40
+ alias is_src is_src?
41
+
42
+ def src
43
+ return unless is_src?
44
+ Ro.render_src(path, node)
45
+ end
46
+
47
+ def stat
48
+ @path.stat.size
49
+ end
50
+
51
+ def size
52
+ stat.size
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,23 @@
1
+ module Ro
2
+ class Collection
3
+ class List < ::Array
4
+ include Klass
5
+
6
+ attr_reader :root
7
+
8
+ def initialize(root, ...)
9
+ @root = root
10
+ super(...)
11
+ end
12
+
13
+ def get(name)
14
+ @root.get(name)
15
+ end
16
+
17
+ def [](index, ...)
18
+ return get(index) if [String, Symbol].include?(index.class)
19
+ super(index, ...)
20
+ end
21
+ end
22
+ end
23
+ end