Class: Ro::Node
Instance Attribute Summary collapse
-
#path ⇒ Object
readonly
Returns the value of attribute path.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
Instance Method Summary collapse
- #<=>(other) ⇒ Object
- #[](*args) ⇒ Object
- #_ignored_files ⇒ Object
- #_load_asset_attributes ⇒ Object
- #_load_base_attributes ⇒ Object
- #_load_file_attributes ⇒ Object
- #_load_meta_attributes ⇒ Object
- #_render(file) ⇒ Object
- #_render_context ⇒ Object
- #as_json ⇒ Object
- #asset_dir ⇒ Object
- #asset_for(*args) ⇒ Object
- #asset_for?(*args, &block) ⇒ Boolean
- #asset_paths ⇒ Object
- #asset_urls ⇒ Object
- #assets ⇒ Object
- #attributes ⇒ Object
- #collection ⇒ Object
- #created_at ⇒ Object
- #default_sort_key ⇒ Object
- #fetch(*args) ⇒ Object
- #files ⇒ Object
- #get(*args) ⇒ Object
- #id ⇒ Object
- #identifier ⇒ Object
-
#initialize(path) ⇒ Node
constructor
A new instance of Node.
- #inspect ⇒ Object
- #load_attributes ⇒ Object
- #load_attributes! ⇒ Object
- #method_missing(method, *args, &block) ⇒ Object
- #name ⇒ Object
- #path_for ⇒ Object
- #relative_path ⇒ Object
- #sort_key ⇒ Object
- #src_for(*args) ⇒ Object
- #to_hash ⇒ Object
- #to_json ⇒ Object
- #to_s ⇒ Object
- #to_str ⇒ Object
- #to_yaml ⇒ Object
- #type ⇒ Object
- #update_attributes!(attrs = {}, **context) ⇒ Object
- #updated_at ⇒ Object
- #url_for(relative_path, options = {}) ⇒ Object
- #urls ⇒ Object
Methods included from Klass
Constructor Details
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object
272 273 274 275 276 277 278 279 280 |
# File 'lib/ro/node.rb', line 272 def method_missing(method, *args, &block) key = method.to_s if attributes.has_key?(key) attributes[key] else super end end |
Instance Attribute Details
#path ⇒ Object (readonly)
Returns the value of attribute path.
5 6 7 |
# File 'lib/ro/node.rb', line 5 def path @path end |
Instance Method Details
#<=>(other) ⇒ Object
314 315 316 |
# File 'lib/ro/node.rb', line 314 def <=>(other) sort_key <=> other.sort_key end |
#[](*args) ⇒ Object
201 202 203 |
# File 'lib/ro/node.rb', line 201 def [](*args) attributes.get(*args) end |
#_ignored_files ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/ro/node.rb', line 153 def _ignored_files ignored_files = %w[ attributes.yml attributes.yaml attributes.json ./assets/**/** ].map do |glob| @path.glob(glob).select(&:file?) end ignored_files.flatten end |
#_load_asset_attributes ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/ro/node.rb', line 66 def _load_asset_attributes {}.tap do |hash| assets.each do |asset| key = asset.name url = asset.url path = asset.path.relative_to(@root) src = asset.src img = asset.img size = asset.size value = { url:, path:, size:, img:, src: } hash[key] = value end @attributes.set(assets: hash) end end |
#_load_base_attributes ⇒ Object
57 58 59 60 61 62 63 64 |
# File 'lib/ro/node.rb', line 57 def _load_base_attributes glob = "attributes.{yml,yaml,json}" @path.glob(glob) do |file| attrs = _render(file) update_attributes!(attrs, file:) end end |
#_load_file_attributes ⇒ Object
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/ro/node.rb', line 100 def _load_file_attributes ignored = _ignored_files @path.files.each do |file| next if ignored.include?(file) rel = file.relative_to(@path) key = rel.parts basename = key.pop base = basename.split('.', 2).first key.push(base) value = _render(file) if value.is_a?(HTML) attrs = value.front_matter update_attributes!(attrs, file:) end if @attributes.has?(key) raise Error.new("path=#{ @path.inspect } masks #{ key.inspect } in #{ @attributes.inspect }!") end @attributes.set(key => value) end end |
#_load_meta_attributes ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/ro/node.rb', line 85 def {}.tap do |hash| hash.update( identifier:, type:, id:, urls:, created_at:, updated_at:, ) @attributes.set(_meta: hash) end end |
#_render(file) ⇒ Object
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/ro/node.rb', line 167 def _render(file) node = self value = Ro.render(file, _render_context) if value.is_a?(HTML) front_matter = value.front_matter html = Ro.(value, node) value = HTML.new(html, front_matter:) end if value.is_a?(Hash) attributes = value value = Ro.(attributes, node) end value end |
#_render_context ⇒ Object
186 187 188 189 190 191 |
# File 'lib/ro/node.rb', line 186 def _render_context to_hash.tap do |context| context[:ro] ||= root context[:collection] ||= collection end end |
#as_json ⇒ Object
298 299 300 |
# File 'lib/ro/node.rb', line 298 def as_json(...) to_hash.as_json(...) end |
#asset_dir ⇒ Object
209 210 211 |
# File 'lib/ro/node.rb', line 209 def asset_dir path.join('assets') end |
#asset_for(*args) ⇒ Object
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/ro/node.rb', line 225 def asset_for(*args) = Map.(args) path_info = Path.relative(args) path = @path.join('assets', path_info) glob = path_info.gsub(/[_-]/, '[_-]') globs = [ @path.call('assets', "#{glob}"), @path.call('assets', "#{glob}*"), @path.call('assets', "**/#{glob}*") ] candidates = globs.map { |glob| Dir.glob(glob, ::File::FNM_CASEFOLD) }.flatten.compact.uniq.sort case candidates.size when 0 raise ArgumentError, "no asset matching #{globs.inspect}" else path = candidates.last end Asset.for(path, node: self) end |
#asset_for?(*args, &block) ⇒ Boolean
253 254 255 256 257 |
# File 'lib/ro/node.rb', line 253 def asset_for?(*args, &block) asset_for(*args, &block) rescue StandardError nil end |
#asset_paths ⇒ Object
213 214 215 |
# File 'lib/ro/node.rb', line 213 def asset_paths asset_dir.select { |entry| entry.file? }.sort end |
#asset_urls ⇒ Object
221 222 223 |
# File 'lib/ro/node.rb', line 221 def asset_urls assets.map(&:url) end |
#assets ⇒ Object
217 218 219 |
# File 'lib/ro/node.rb', line 217 def assets asset_paths.map { |path| Asset.for(path, node: self) } end |
#attributes ⇒ Object
37 38 39 40 |
# File 'lib/ro/node.rb', line 37 def attributes load_attributes @attributes end |
#collection ⇒ Object
33 34 35 |
# File 'lib/ro/node.rb', line 33 def collection @root.collection_for(type) end |
#created_at ⇒ Object
330 331 332 |
# File 'lib/ro/node.rb', line 330 def created_at files.map{|file| File.stat(file).ctime}.min end |
#default_sort_key ⇒ Object
322 323 324 325 326 327 328 |
# File 'lib/ro/node.rb', line 322 def default_sort_key position = (attributes[:position] ? Float(attributes[:position]) : 0.0) published_at = (attributes[:published_at] ? Time.parse(attributes[:published_at].to_s) : Time.at(0)).utc.iso8601 created_at = (attributes[:created_at] ? Time.parse(attributes[:created_at].to_s) : Time.at(0)).utc.iso8601 [position, published_at, created_at, name] end |
#fetch(*args) ⇒ Object
193 194 195 |
# File 'lib/ro/node.rb', line 193 def fetch(*args) attributes.fetch(*args) end |
#files ⇒ Object
306 307 308 |
# File 'lib/ro/node.rb', line 306 def files path.glob('**/**').select { |entry| entry.file? }.sort end |
#get(*args) ⇒ Object
197 198 199 |
# File 'lib/ro/node.rb', line 197 def get(*args) attributes.get(*args) end |
#id ⇒ Object
17 18 19 |
# File 'lib/ro/node.rb', line 17 def id name end |
#identifier ⇒ Object
25 26 27 |
# File 'lib/ro/node.rb', line 25 def identifier File.join(type, id) end |
#inspect ⇒ Object
29 30 31 |
# File 'lib/ro/node.rb', line 29 def inspect identifier end |
#load_attributes ⇒ Object
42 43 44 |
# File 'lib/ro/node.rb', line 42 def load_attributes load_attributes! if @attributes == :lazyload end |
#load_attributes! ⇒ Object
46 47 48 49 50 51 52 53 54 55 |
# File 'lib/ro/node.rb', line 46 def load_attributes! @attributes = Map.new _load_base_attributes _load_file_attributes _load_asset_attributes @attributes end |
#name ⇒ Object
13 14 15 |
# File 'lib/ro/node.rb', line 13 def name @path.name end |
#path_for ⇒ Object
263 264 265 |
# File 'lib/ro/node.rb', line 263 def path_for(...) @path.join(...) end |
#relative_path ⇒ Object
205 206 207 |
# File 'lib/ro/node.rb', line 205 def relative_path path.relative_to(root) end |
#sort_key ⇒ Object
318 319 320 |
# File 'lib/ro/node.rb', line 318 def sort_key default_sort_key end |
#src_for(*args) ⇒ Object
267 268 269 270 |
# File 'lib/ro/node.rb', line 267 def src_for(*args) key = Path.relative(:assets, :src, args).split('/') get(key) end |
#to_hash ⇒ Object
282 283 284 |
# File 'lib/ro/node.rb', line 282 def to_hash attributes.to_hash end |
#to_json ⇒ Object
294 295 296 |
# File 'lib/ro/node.rb', line 294 def to_json(...) JSON.pretty_generate(to_hash, ...) end |
#to_s ⇒ Object
286 287 288 |
# File 'lib/ro/node.rb', line 286 def to_s(...) to_json(...) end |
#to_str ⇒ Object
290 291 292 |
# File 'lib/ro/node.rb', line 290 def to_str(...) to_json(...) end |
#to_yaml ⇒ Object
302 303 304 |
# File 'lib/ro/node.rb', line 302 def to_yaml(...) to_hash.to_yaml(...) end |
#type ⇒ Object
21 22 23 |
# File 'lib/ro/node.rb', line 21 def type @path.parent.name end |
#update_attributes!(attrs = {}, **context) ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/ro/node.rb', line 128 def update_attributes!(attrs = {}, **context) attrs = Map.for(attrs) blacklist = %w[ assets _meta ] blacklist.each do |key| if attrs.has_key?(key) Ro.error!("#{ key } is blacklisted!", **context) end end keys = @attributes.depth_first_keys attrs.depth_first_keys.each do |key| if keys.include?(key) Ro.error!("#{ attrs.inspect } clobbers #{ @attributes.inspect }!", **context) end end @attributes.update(attrs) end |
#updated_at ⇒ Object
334 335 336 |
# File 'lib/ro/node.rb', line 334 def updated_at files.map{|file| File.stat(file).mtime}.max end |
#url_for(relative_path, options = {}) ⇒ Object
259 260 261 |
# File 'lib/ro/node.rb', line 259 def url_for(relative_path, = {}) Ro.url_for(self.relative_path, relative_path, ) end |
#urls ⇒ Object
310 311 312 |
# File 'lib/ro/node.rb', line 310 def urls files.map { |file| url_for(file.relative_to(@path)) }.sort end |