Class: Webgen::Node
- Inherits:
-
Object
- Object
- Webgen::Node
- Includes:
- Loggable, WebsiteAccess
- Defined in:
- lib/webgen/node.rb,
lib/webgen/deprecated.rb
Overview
Represents a file, a directory or a fragment. A node always belongs to a Tree.
All needed meta and processing information is associated with a Node. The meta information is available throught the #[] and #meta_info accessors, the processing information through the #node_info accessor.
Although node information should be changed by code, it is not advised to change meta information values in code since this may lead to unwanted behaviour!
Constant Summary collapse
- URL_UNSAFE_PATTERN =
This pattern is the the same as URI::UNSAFE except that the hash character (#) is also not escaped. This is needed sothat paths with fragments work correctly.
Regexp.new("[^#{URI::PATTERN::UNRESERVED}#{URI::PATTERN::RESERVED}#]")
Instance Attribute Summary collapse
-
#acn ⇒ Object
readonly
The absolute canonical name of this node.
-
#alcn ⇒ Object
readonly
The absolute localized canonical name of this node.
-
#children ⇒ Object
readonly
The child nodes 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
-
.url(name, make_absolute = true) ⇒ Object
Construct an internal URL for the given
name
which can be an acn/alcn/path.
Instance Method Summary collapse
-
#<=>(other) ⇒ Object
Sort nodes by using the meta info
sort_info
(ortitle
ifsort_info
is not set) of both involved nodes. -
#=~(pattern) ⇒ Object
Return
true
if the alcn matches the pattern. -
#[](key) ⇒ Object
Return the meta information item for
key
. -
#[]=(key, value) ⇒ Object
Assign
value
to the meta information item forkey
. - #absolute_cn ⇒ Object
- #absolute_lcn ⇒ Object
-
#changed? ⇒ Boolean
Return
true
if the node has changed since the last webgen run. -
#flag(*keys) ⇒ Object
Flag the node with the
keys
and dispatch the message:node_flagged
withself
andkeys
as arguments. - #flagged(key) ⇒ Object
-
#flagged?(key) ⇒ Boolean
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
lang
or, 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
node
or, if this node andnode
are the same and the parameterwebsite.link_to_current_page
isfalse
, aspan
element with the link text. -
#meta_info_changed? ⇒ Boolean
Return
true
if 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, use_passive_sources = true) ⇒ Object
Return the node representing the given
path
which can be an acn/alcn. -
#route_to(other) ⇒ Object
Return the relative path to the given path
other
. -
#routing_node(lang, log_warning = true) ⇒ Object
Return the routing node in language
lang
which is the node that is used when routing to this node. -
#unflag(*keys) ⇒ Object
Remove the flags
keys
from the node and dispatch the message:node_unflagged
withself
andkeys
as arguments.
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 likehttp://myhost.com/
. cn
(immutable)-
The canonical name for this node. Needs to be of the form
basename.ext
orbasename
wherebasename
does not contain any dots. Also, thebasename
must not include a language part! meta_info
-
A 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.
78 79 80 81 82 83 84 |
# File 'lib/webgen/node.rb', line 78 def initialize(parent, path, cn, = {}) @parent = parent @cn = cn.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.
380 381 382 383 384 385 386 |
# File 'lib/webgen/node.rb', line 380 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
#acn ⇒ Object (readonly)
The absolute canonical name of this node.
42 43 44 |
# File 'lib/webgen/node.rb', line 42 def acn @acn end |
#alcn ⇒ Object (readonly)
The absolute localized canonical name of this node.
48 49 50 |
# File 'lib/webgen/node.rb', line 48 def alcn @alcn end |
#children ⇒ Object (readonly)
The child nodes of this node.
30 31 32 |
# File 'lib/webgen/node.rb', line 30 def children @children end |
#cn ⇒ Object (readonly)
The canonical name of this node.
39 40 41 |
# File 'lib/webgen/node.rb', line 39 def cn @cn end |
#lang ⇒ Object (readonly)
The language of this node.
54 55 56 |
# File 'lib/webgen/node.rb', line 54 def lang @lang end |
#lcn ⇒ Object (readonly)
The localized canonical name of this node.
45 46 47 |
# File 'lib/webgen/node.rb', line 45 def lcn @lcn end |
#level ⇒ Object (readonly)
The level of the node. The level specifies how deep the node is in the hierarchy.
51 52 53 |
# File 'lib/webgen/node.rb', line 51 def level @level end |
#meta_info ⇒ Object (readonly)
Meta information associated with the node.
57 58 59 |
# File 'lib/webgen/node.rb', line 57 def @meta_info end |
#parent ⇒ Object (readonly)
The parent node. This is in all but one case a Node object. The one exception is that the parent of the Tree#dummy_node is a Tree object.
27 28 29 |
# File 'lib/webgen/node.rb', line 27 def parent @parent end |
#path ⇒ Object (readonly)
The full output path of this node.
33 34 35 |
# File 'lib/webgen/node.rb', line 33 def path @path end |
#tree ⇒ Object (readonly)
The tree to which this node belongs.
36 37 38 |
# File 'lib/webgen/node.rb', line 36 def tree @tree end |
Class Method Details
.url(name, make_absolute = true) ⇒ Object
Construct an internal URL for the given name
which can be an acn/alcn/path. If the parameter make_absolute
is true
, then a relative URL will be made absolute by prepending the special URL webgen:://webgen.localhost/
.
214 215 216 217 218 |
# File 'lib/webgen/node.rb', line 214 def self.url(name, make_absolute = true) url = URI::parse(URI::escape(name, URL_UNSAFE_PATTERN)) url = URI::parse('webgen://webgen.localhost/') + url unless url.absolute? || !make_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.
197 198 199 200 201 202 203 204 205 |
# File 'lib/webgen/node.rb', line 197 def <=>(other) self_so = (@meta_info['sort_info'] && @meta_info['sort_info'].to_s) || @meta_info['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.
191 192 193 |
# File 'lib/webgen/node.rb', line 191 def =~(pattern) File.fnmatch(pattern, @alcn, File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME) end |
#[](key) ⇒ Object
Return the meta information item for key
.
104 105 106 |
# File 'lib/webgen/node.rb', line 104 def [](key) @meta_info[key] end |
#[]=(key, value) ⇒ Object
Assign value
to the meta information item for key
.
109 110 111 |
# File 'lib/webgen/node.rb', line 109 def []=(key, value) @meta_info[key] = value end |
#absolute_cn ⇒ Object
10 11 12 13 |
# File 'lib/webgen/deprecated.rb', line 10 def absolute_cn warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Node#acn instead!") acn end |
#absolute_lcn ⇒ Object
15 16 17 18 |
# File 'lib/webgen/deprecated.rb', line 15 def absolute_lcn warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Node#alcn instead!") alcn end |
#changed? ⇒ Boolean
Return true
if the node has changed since the last webgen run. If it has changed, dirty
is set to true
.
Sends the message :node_changed?
with self
as argument unless the node is already dirty. A listener to this message should set the flag :dirty
on the passed node if he thinks it is dirty.
162 163 164 165 166 167 168 169 170 |
# File 'lib/webgen/node.rb', line 162 def changed? if_not_checked(:node) do flag(:dirty) if || node_info[:used_nodes].any? {|n| n != @alcn && (!tree[n] || tree[n].changed?)} || node_info[:used_meta_info_nodes].any? {|n| n != @alcn && (!tree[n] || tree[n].)} website.blackboard.dispatch_msg(:node_changed?, self) unless flagged?(:dirty) end flagged?(:dirty) end |
#flag(*keys) ⇒ Object
Flag the node with the keys
and dispatch the message :node_flagged
with self
and keys
as arguments. See #flagged for valid keys.
144 145 146 147 |
# File 'lib/webgen/node.rb', line 144 def flag(*keys) @flags += keys website.blackboard.dispatch_msg(:node_flagged, self, keys) end |
#flagged(key) ⇒ Object
5 6 7 8 |
# File 'lib/webgen/deprecated.rb', line 5 def flagged(key) warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Node#flagged? instead!") flagged?(key) end |
#flagged?(key) ⇒ Boolean
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 tofalse
once it istrue
! - :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 tofalse
once it istrue
!
138 139 140 |
# File 'lib/webgen/node.rb', line 138 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.
232 233 234 235 236 237 238 239 240 241 |
# File 'lib/webgen/node.rb', line 232 def in_lang(lang) avail = @tree.node_access[:acn][@acn] 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!
223 224 225 226 227 |
# File 'lib/webgen/node.rb', line 223 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.
186 187 188 |
# File 'lib/webgen/node.rb', line 186 def inspect "<##{self.class.name}: alcn=#{@alcn}>" end |
#is_directory? ⇒ Boolean
Check if the node is a directory.
119 |
# File 'lib/webgen/node.rb', line 119 def is_directory?; @path[-1] == ?/ && !is_fragment?; end |
#is_file? ⇒ Boolean
Check if the node is a file.
122 |
# File 'lib/webgen/node.rb', line 122 def is_file?; !is_directory? && !is_fragment?; end |
#is_fragment? ⇒ Boolean
Check if the node is a fragment.
125 |
# File 'lib/webgen/node.rb', line 125 def is_fragment?; @cn[0] == ?# end |
#is_root? ⇒ Boolean
Check if the node is the root node.
128 |
# File 'lib/webgen/node.rb', line 128 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.
334 335 336 337 338 339 340 341 342 343 344 |
# File 'lib/webgen/node.rb', line 334 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.
Sends the message :node_meta_info_changed?
with self
as argument unless the meta information of the node is already dirty. A listener to this message should set the flag :dirt_meta_info
on the passed node if he thinks that the node’s meta information is dirty.
178 179 180 181 182 183 |
# File 'lib/webgen/node.rb', line 178 def if_not_checked(:meta_info) do 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.
114 115 116 |
# File 'lib/webgen/node.rb', line 114 def node_info tree.node_info[@alcn] ||= {} end |
#reinit(path, meta_info = {}) ⇒ Object
Re-initializes an already initialized node and resets it to its pristine state.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/webgen/node.rb', line 87 def reinit(path, = {}) old_path = @path if defined?(@path) @path = path.freeze @lang = Webgen::LanguageManager.language_for_code(.delete('lang')) @lang = nil unless is_file? @meta_info = @flags = Set.new([:dirty, :created]) if defined?(@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, use_passive_sources = true) ⇒ 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.
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/webgen/node.rb', line 250 def resolve(path, lang = nil, use_passive_sources = true) orig_path = path url = self.class.url(@alcn) + self.class.url(path, false) path = url.path + (url.fragment.nil? ? '' : '#' + url.fragment) return nil if path =~ /^\/\.\./ node = @tree[path, :alcn] if !node || node.acn == path (node = (@tree[path, :acn] || @tree[path + '/', :acn])) && (node = node.in_lang(lang)) end if !node && use_passive_sources && !website.config['passive_sources'].empty? nodes = website.blackboard.invoke(:create_nodes_from_paths, [path]) node = resolve(orig_path, lang, false) node.node_info[:used_meta_info_nodes] += nodes.collect {|n| n.alcn} if node end node end |
#route_to(other) ⇒ Object
Return the relative path to the given path other
. The parameter other
can be a Node or a String.
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
# File 'lib/webgen/node.rb', line 271 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, log_warning = true) ⇒ 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. If show_warning
is true
and this node is a directory node, then a warning is logged if no associated index file is found.
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/webgen/node.rb', line 293 def routing_node(lang, log_warning = true) if !is_directory? self else key = [alcn, :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 <#{alcn}> => <#{index_node.alcn}>" } elsif log_warning vcache[key] = self log(:warn) { "No directory index path found for directory <#{alcn}>" } end end vcache[key] || self end end |
#unflag(*keys) ⇒ Object
Remove the flags keys
from the node and dispatch the message :node_unflagged
with self
and keys
as arguments.
151 152 153 154 |
# File 'lib/webgen/node.rb', line 151 def unflag(*keys) @flags.subtract(keys) website.blackboard.dispatch_msg(:node_unflagged, self, keys) end |