Class: Webgen::Node
- Inherits:
-
Object
- Object
- Webgen::Node
- Includes:
- Loggable, WebsiteAccess
- Defined in:
- lib/webgen/node.rb
Overview
Represents a file, a directory or a fragment. A node always belongs to a Tree.
Instance Attribute Summary collapse
-
#absolute_cn ⇒ Object
readonly
The absolute canonical name of this node.
-
#absolute_lcn ⇒ Object
readonly
The absolute localized canonical name of this node.
-
#children ⇒ Object
readonly
The children of this node.
-
#cn ⇒ Object
readonly
The canonical name of this node.
-
#lang ⇒ Object
readonly
The language of this node.
-
#lcn ⇒ Object
readonly
The localized canonical name of this node.
-
#level ⇒ Object
readonly
The level of the node.
-
#meta_info ⇒ Object
readonly
Meta information associated with the node.
-
#parent ⇒ Object
readonly
The parent node.
-
#path ⇒ Object
readonly
The full output path of this node.
-
#tree ⇒ Object
readonly
The tree to which this node belongs.
Class Method Summary collapse
-
.absolute_name(parent, name, type) ⇒ Object
Construct the absolute (localized) canonical name by using the
parentnode andname(which can be a cn or an lcn). -
.url(name) ⇒ Object
Construct an internal URL for the given
namewhich can be a acn/alcn/path.
Instance Method Summary collapse
-
#<=>(other) ⇒ Object
Sort nodes by using the meta info
sort_info(ortitleifsort_infois not set) of both involved nodes. -
#=~(pattern) ⇒ Object
Return
trueif the alcn matches the pattern. -
#[](key) ⇒ Object
Return the meta information item for
key. -
#[]=(key, value) ⇒ Object
Assign
valueto the meta information item forkey. -
#changed? ⇒ Boolean
Return
trueif the node has changed since the last webgen run. -
#flag(*keys) ⇒ Object
Flag the node with the
keys. -
#flagged(key) ⇒ Object
Check if the node is flagged with one of the following:.
-
#in_lang(lang) ⇒ Object
Return the node with the same canonical name but in language
langor, if no such node exists, an unlocalized version of the node. -
#in_subtree_of?(node) ⇒ Boolean
Check if the this node is in the subtree which is spanned by
node. -
#initialize(parent, path, cn, meta_info = {}) ⇒ Node
constructor
Create a new Node instance.
-
#inspect ⇒ Object
Return an informative representation of the node.
-
#is_directory? ⇒ Boolean
Check if the node is a directory.
-
#is_file? ⇒ Boolean
Check if the node is a file.
-
#is_fragment? ⇒ Boolean
Check if the node is a fragment.
-
#is_root? ⇒ Boolean
Check if the node is the root node.
-
#link_to(node, attr = {}) ⇒ Object
Return a HTML link from this node to the
nodeor, if this node andnodeare the same and the parameter website.link_to_current_page isfalse, aspanelement with the link text. -
#meta_info_changed? ⇒ Boolean
Return
trueif the meta information of the node has changed. -
#node_info ⇒ Object
Return the node information hash which contains information for processing the node.
-
#reinit(path, meta_info = {}) ⇒ Object
Re-initializes an already initialized node and resets it to its pristine state.
-
#resolve(path, lang = nil) ⇒ Object
Return the node representing the given
pathwhich can be an acn/alcn. -
#route_to(other) ⇒ Object
Return the relative path to the given path
other. -
#routing_node(lang) ⇒ Object
Return the routing node in language
langwhich is the node that is used when routing to this node. -
#unflag(*keys) ⇒ Object
Remove the flags
keysfrom the node.
Methods included from Loggable
Methods included from WebsiteAccess
Constructor Details
#initialize(parent, path, cn, meta_info = {}) ⇒ Node
Create a new Node instance.
parent(immutable)The parent node under which this nodes should be created.
path(immutable)The full output path for this node. If this node is a directory, the path must have a trailing slash (dir/). If it is a fragment, the hash sign must be the first character of the path (#fragment). This can also be an absolute path like http://myhost.com/.
cn(immutable)The canonical name for this node. Needs to be of the form basename.ext or basename where
basenamedoes not contain any dots. Also, thebasenamemust not include a language part!meta_infoA hash with meta information for the new node.
The language of a node is taken from the meta information lang and the entry is deleted from
the meta information hash. The language cannot be changed afterwards! If no lang key is
found, the node is language neutral.
68 69 70 71 72 73 74 |
# File 'lib/webgen/node.rb', line 68 def initialize(parent, path, cn, = {}) @parent = parent @cn = cn.chomp('/').freeze @children = [] reinit(path, ) init_rest end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object (private)
Delegate missing methods to a processor. The current node is placed into the argument array as
the first argument before the method name is invoked on the processor.
362 363 364 365 366 367 368 |
# File 'lib/webgen/node.rb', line 362 def method_missing(name, *args, &block) if node_info[:processor] website.cache.instance(node_info[:processor]).send(name, *([self] + args), &block) else super end end |
Instance Attribute Details
#absolute_cn ⇒ Object (readonly)
The absolute canonical name of this node.
32 33 34 |
# File 'lib/webgen/node.rb', line 32 def absolute_cn @absolute_cn end |
#absolute_lcn ⇒ Object (readonly)
The absolute localized canonical name of this node.
38 39 40 |
# File 'lib/webgen/node.rb', line 38 def absolute_lcn @absolute_lcn end |
#children ⇒ Object (readonly)
The children of this node.
20 21 22 |
# File 'lib/webgen/node.rb', line 20 def children @children end |
#cn ⇒ Object (readonly)
The canonical name of this node.
29 30 31 |
# File 'lib/webgen/node.rb', line 29 def cn @cn end |
#lang ⇒ Object (readonly)
The language of this node.
44 45 46 |
# File 'lib/webgen/node.rb', line 44 def lang @lang end |
#lcn ⇒ Object (readonly)
The localized canonical name of this node.
35 36 37 |
# File 'lib/webgen/node.rb', line 35 def lcn @lcn end |
#level ⇒ Object (readonly)
The level of the node. The level specifies how deep the node is in the hierarchy.
41 42 43 |
# File 'lib/webgen/node.rb', line 41 def level @level end |
#meta_info ⇒ Object (readonly)
Meta information associated with the node.
47 48 49 |
# File 'lib/webgen/node.rb', line 47 def end |
#parent ⇒ Object (readonly)
The parent node.
17 18 19 |
# File 'lib/webgen/node.rb', line 17 def parent @parent end |
#path ⇒ Object (readonly)
The full output path of this node.
23 24 25 |
# File 'lib/webgen/node.rb', line 23 def path @path end |
#tree ⇒ Object (readonly)
The tree to which this node belongs.
26 27 28 |
# File 'lib/webgen/node.rb', line 26 def tree @tree end |
Class Method Details
.absolute_name(parent, name, type) ⇒ Object
Construct the absolute (localized) canonical name by using the parent node and name (which
can be a cn or an lcn). The type can be either :alcn or :acn.
190 191 192 193 194 195 196 197 198 |
# File 'lib/webgen/node.rb', line 190 def self.absolute_name(parent, name, type) if parent.kind_of?(Tree) '' else parent = parent.parent while parent.is_fragment? # Handle fragment nodes specially in case they are nested parent_name = (type == :alcn ? parent.absolute_lcn : parent.absolute_cn) parent_name + (parent_name !~ /\/$/ && (parent.is_directory? || parent == parent.tree.dummy_root) ? '/' : '') + name end end |
.url(name) ⇒ Object
Construct an internal URL for the given name which can be a acn/alcn/path.
201 202 203 204 205 |
# File 'lib/webgen/node.rb', line 201 def self.url(name) url = URI::parse(name) url = URI::parse('webgen://webgen.localhost/') + url unless url.absolute? url end |
Instance Method Details
#<=>(other) ⇒ Object
Sort nodes by using the meta info sort_info (or title if sort_info is not set) of both
involved nodes.
178 179 180 181 182 183 184 185 186 |
# File 'lib/webgen/node.rb', line 178 def <=>(other) self_so = (['sort_info'] && ['sort_info'].to_s) || ['title'] || '' other_so = (other['sort_info'] && other['sort_info'].to_s) || other['title'] || '' if self_so !~ /\D/ && other_so !~ /\D/ self_so = self_so.to_i other_so = other_so.to_i end self_so <=> other_so end |
#=~(pattern) ⇒ Object
Return true if the alcn matches the pattern. See File.fnmatch for useable patterns.
172 173 174 |
# File 'lib/webgen/node.rb', line 172 def =~(pattern) File.fnmatch(pattern, @absolute_lcn, File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME) end |
#[](key) ⇒ Object
Return the meta information item for key.
94 95 96 |
# File 'lib/webgen/node.rb', line 94 def [](key) [key] end |
#[]=(key, value) ⇒ Object
Assign value to the meta information item for key.
99 100 101 |
# File 'lib/webgen/node.rb', line 99 def []=(key, value) [key] = value end |
#changed? ⇒ Boolean
Return true if the node has changed since the last webgen run. If it has changed, dirty is
set to true.
146 147 148 149 150 151 152 153 |
# File 'lib/webgen/node.rb', line 146 def changed? if_not_checked(:node) do flag(:dirty) if || node_info[:used_nodes].any? {|n| n != @absolute_lcn && (!tree[n] || tree[n].changed?)} website.blackboard.dispatch_msg(:node_changed?, self) unless flagged(:dirty) end flagged(:dirty) end |
#flag(*keys) ⇒ Object
Flag the node with the keys. See #flagged for valid keys.
133 134 135 136 |
# File 'lib/webgen/node.rb', line 133 def flag(*keys) @flags += keys website.blackboard.dispatch_msg(:node_flagged, self, keys) end |
#flagged(key) ⇒ Object
Check if the node is flagged with one of the following:
:created:: Has the node been created or has it been read from the cache?
:reinit:: Does the node need to be reinitialized?
:dirty:: Set by other objects to true if they think the object has changed since the last
run. Must not be set to false once it is true!
:dirty_meta_info:: Set by other objects to true if the meta information of the node has
changed since the last run. Must not be set to false once it is true!
128 129 130 |
# File 'lib/webgen/node.rb', line 128 def flagged(key) @flags.include?(key) end |
#in_lang(lang) ⇒ Object
Return the node with the same canonical name but in language lang or, if no such node
exists, an unlocalized version of the node. If no such node is found either, nil is
returned.
219 220 221 222 223 224 225 226 227 228 |
# File 'lib/webgen/node.rb', line 219 def in_lang(lang) avail = @tree.node_access[:acn][@absolute_cn] avail.find do |n| n = n.parent while n.is_fragment? n.lang == lang end || avail.find do |n| n = n.parent while n.is_fragment? n.lang.nil? end end |
#in_subtree_of?(node) ⇒ Boolean
Check if the this node is in the subtree which is spanned by node. The check is performed
using only the parent information of the involved nodes, NOT the actual path/alcn values!
210 211 212 213 214 |
# File 'lib/webgen/node.rb', line 210 def in_subtree_of?(node) temp = self temp = temp.parent while temp != tree.dummy_root && temp != node temp != tree.dummy_root end |
#inspect ⇒ Object
Return an informative representation of the node.
167 168 169 |
# File 'lib/webgen/node.rb', line 167 def inspect "<##{self.class.name}: alcn=#{@absolute_lcn}>" end |
#is_directory? ⇒ Boolean
Check if the node is a directory.
109 |
# File 'lib/webgen/node.rb', line 109 def is_directory?; @path[-1] == ?/; end |
#is_file? ⇒ Boolean
Check if the node is a file.
112 |
# File 'lib/webgen/node.rb', line 112 def is_file?; !is_directory? && !is_fragment?; end |
#is_fragment? ⇒ Boolean
Check if the node is a fragment.
115 |
# File 'lib/webgen/node.rb', line 115 def is_fragment?; @cn[0] == ?# end |
#is_root? ⇒ Boolean
Check if the node is the root node.
118 |
# File 'lib/webgen/node.rb', line 118 def is_root?; self == tree.root; end |
#link_to(node, attr = {}) ⇒ Object
Return a HTML link from this node to the node or, if this node and node are the same and
the parameter website.link_to_current_page is false, a span element with the link
text.
You can optionally specify additional attributes for the HTML element in the attr Hash.
Also, the meta information link_attrs of the given node is used, if available, to set
attributes. However, the attr parameter takes precedence over the link_attrs meta
information. Be aware that all key-value pairs with Symbol keys are removed before the
attributes are written. Therefore you always need to specify general attributes with Strings!
If the special value :link_text is present in the attributes, it will be used as the
link text; otherwise the title of the node will be used.
If the special value :lang is present in the attributes, it will be used as parameter
to the node.routing_node call for getting the linked-to node instead of this node's
lang attribute. Note: this is only useful when linking to a directory.
316 317 318 319 320 321 322 323 324 325 326 |
# File 'lib/webgen/node.rb', line 316 def link_to(node, attr = {}) attr = node['link_attrs'].merge(attr) if node['link_attrs'].kind_of?(Hash) rnode = node.routing_node(attr[:lang] || @lang) link_text = attr[:link_text] || (rnode != node && rnode['routed_title']) || node['title'] attr.delete_if {|k,v| k.kind_of?(Symbol)} use_link = (rnode != self || website.config['website.link_to_current_page']) attr['href'] = self.route_to(rnode) if use_link attrs = attr.collect {|name,value| "#{name.to_s}=\"#{value}\"" }.sort.unshift('').join(' ') (use_link ? "<a#{attrs}>#{link_text}</a>" : "<span#{attrs}>#{link_text}</span>") end |
#meta_info_changed? ⇒ Boolean
Return true if the meta information of the node has changed.
156 157 158 159 160 161 162 163 164 |
# File 'lib/webgen/node.rb', line 156 def if_not_checked(:meta_info) do flag(:dirty_meta_info) if node_info[:used_meta_info_nodes].any? do |n| n != @absolute_lcn && (!tree[n] || tree[n].) end website.blackboard.dispatch_msg(:node_meta_info_changed?, self) unless flagged(:dirty_meta_info) end flagged(:dirty_meta_info) end |
#node_info ⇒ Object
Return the node information hash which contains information for processing the node.
104 105 106 |
# File 'lib/webgen/node.rb', line 104 def node_info tree.node_info[@absolute_lcn] ||= {} end |
#reinit(path, meta_info = {}) ⇒ Object
Re-initializes an already initialized node and resets it to its pristine state.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/webgen/node.rb', line 77 def reinit(path, = {}) old_path = @path @path = path.freeze @lang = Webgen::LanguageManager.language_for_code(.delete('lang')) @lang = nil unless is_file? = @flags = Set.new([:dirty, :created]) if @tree @tree.node_access[:path].delete(old_path) if old_path @tree.register_path(self) self.node_info.clear self.node_info[:used_nodes] = Set.new self.node_info[:used_meta_info_nodes] = Set.new end end |
#resolve(path, lang = nil) ⇒ Object
Return the node representing the given path which can be an acn/alcn. The path can be
absolute (i.e. starting with a slash) or relative to the current node. If no node exists for
the given path or if the path is invalid, nil is returned.
If the path is an alcn and a node is found, it is returned. If the path is an acn, the
correct localized node according to lang is returned or if no such node exists but an
unlocalized version does, the unlocalized node is returned.
237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/webgen/node.rb', line 237 def resolve(path, lang = nil) url = self.class.url(self.is_directory? ? File.join(@absolute_lcn, '/') : @absolute_lcn) + path path = url.path + (url.fragment.nil? ? '' : '#' + url.fragment) path.chomp!('/') unless path == '/' return nil if path =~ /^\/\.\./ node = @tree[path, :alcn] if node && node.absolute_cn != path node else (node = @tree[path, :acn]) && node.in_lang(lang) end end |
#route_to(other) ⇒ Object
Return the relative path to the given path other. The parameter other can be a Node or a
String.
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
# File 'lib/webgen/node.rb', line 254 def route_to(other) my_url = self.class.url(@path) other_url = if other.kind_of?(Node) self.class.url(other.routing_node(@lang).path) elsif other.kind_of?(String) my_url + other else raise ArgumentError, "improper class for argument" end # resolve any '.' and '..' paths in the target url if other_url.path =~ /\/\.\.?\// && other_url.scheme == 'webgen' other_url.path = Pathname.new(other_url.path).cleanpath.to_s end route = my_url.route_to(other_url).to_s (route == '' ? File.basename(self.path) : route) end |
#routing_node(lang) ⇒ Object
Return the routing node in language lang which is the node that is used when routing to this
node. The returned node can differ from the node itself in case of a directory where the
routing node is the directory index node.
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'lib/webgen/node.rb', line 275 def routing_node(lang) if !is_directory? self else key = [absolute_lcn, :index_node, lang] vcache = website.cache.volatile return vcache[key] if vcache.has_key?(key) index_path = self.['index_path'] if index_path.nil? vcache[key] = self else index_node = resolve(index_path, lang) if index_node vcache[key] = index_node log(:info) { "Directory index path for <#{absolute_lcn}> => <#{index_node.absolute_lcn}>" } else vcache[key] = self log(:warn) { "No directory index path found for directory <#{absolute_lcn}>" } end end vcache[key] end end |
#unflag(*keys) ⇒ Object
Remove the flags keys from the node.
139 140 141 142 |
# File 'lib/webgen/node.rb', line 139 def unflag(*keys) @flags.subtract(keys) website.blackboard.dispatch_msg(:node_unflagged, self, keys) end |