module Webgen::PathHandler::Base
This module provides the helper methods needed by most, if not all, path handlers.
About¶ ↑
It provides default implementations of all methods expected by Webgen::PathHandler
except create_nodes, namely initialize, parse_meta_info!
and content.
The most important method used when implementing a path handler is probably create_node
which should be used in create_nodes to create an actual Webgen::Node
object from a Webgen::Path
object.
The following utility methods are also provided:
Constants
- DEST_PATH_PARENT_SEGMENTS
Public Class Methods
Initialize the path handler with the given Website
object.
# File lib/webgen/path_handler/base.rb 72 def initialize(website) 73 @website = website 74 end
Public Instance Methods
Update path.meta_info
with meta information found in the content of the path.
This default parse_meta_info!
method does nothing and should be overridden in path handlers that know that additional meta information can be found in the content of the path itself.
Note that the return values of this method are given as extra parameters to the create_nodes method. If you don't handle extra parameters, return an empty array.
# File lib/webgen/path_handler/base.rb 84 def parse_meta_info!(path) 85 [] 86 end
Protected Instance Methods
Create a node from path
, if possible, and yield the fully initialized node if a block is given as well as return it.
Note that the block should be used when the newly created node need to be modified because the returned node can also be a reused node (in case the information in the supplied path applies uniquely to an already existing node)!
The node class to be used for the to-be-created node can be specified via `path.meta_info`. This is normally used by specific path handlers to provide custom node classes.
The default base node class can be changed by setting `path.meta_info`. Note that the `node_class` key takes precedence over this key!
The parent node under which the new node should be created can optionally be specified via 'path.meta_info'. This node processing information has to be set to the alcn of an existing node.
If no node can be created (e.g. when 'path.meta_info' is set), nil
is returned.
On the created node, the node information :path
is set to the given path and :path_handler
to the path handler instance.
# File lib/webgen/path_handler/base.rb 110 def create_node(path) 111 return nil if path.meta_info['draft'] 112 parent = parent_node(path) 113 dest_path = self.dest_path(parent, path) 114 115 if node = node_exists?(path, dest_path) 116 node_path = node.node_info[:path] 117 if node_path != path 118 raise Webgen::NodeCreationError.new("Another node <#{node}> with the same alcn or destination path already exists") 119 elsif node_path.meta_info == path.meta_info 120 @website.blackboard.dispatch_msg(:reused_existing_node, node) 121 return node 122 else 123 node.tree.delete_node(node) 124 end 125 end 126 127 if !path.meta_info['modified_at'].kind_of?(Time) 128 @website.logger.debug do 129 "Meta information 'modified_at' set to current time in <#{path}> since its value #{path.meta_info['modified_at'].inspect} was of type #{path.meta_info['modified_at'].class}" 130 end 131 path.meta_info['modified_at'] = Time.now 132 end 133 134 node = node_class(path).new(parent, path.cn, dest_path, path.meta_info.dup) 135 node.node_info[:path] = path 136 node.node_info[:path_handler] = self 137 138 yield(node) if block_given? 139 node 140 end
Construct the destination path for the given path
and parent
node.
See the user documentation for how a destination path is constructed and which configuration options are used!
First it is checked if a node with the constructed destination path already exists. If it exists, the language part is forced to be in the destination path and the resulting destination path is returned.
# File lib/webgen/path_handler/base.rb 162 def dest_path(parent, path) 163 path.meta_info['dest_path'] ||= '<parent><basename>(-<version>)(-<modified_at>)(.<lang>)<ext>' 164 dpath = construct_dest_path(parent, path, false) 165 if (node = node_exists?(path, dpath)) && node.lang != path.meta_info['lang'] 166 dpath = construct_dest_path(parent, path, true) 167 end 168 dpath 169 end
Retrieve the node class that should be used for the given path.
# File lib/webgen/path_handler/base.rb 267 def node_class(path) 268 if String === (klass = path.meta_info['node_class']) 269 Webgen::Utils.const_for_name(klass) rescue Node 270 elsif String === (klass = path.meta_info['base_node_class']) 271 Webgen::Utils.const_for_name(klass) rescue Node 272 else 273 Node 274 end 275 end
Check if the node alcn or the destination path, which would be created by create_node
for the given paths, exists.
# File lib/webgen/path_handler/base.rb 261 def node_exists?(path, dest_path) 262 @website.tree[path.alcn] || (!path.meta_info['no_output'] && @website.tree.node(dest_path, :dest_path)) 263 end
Return the parent node for the given path
.
# File lib/webgen/path_handler/base.rb 144 def parent_node(path) 145 parent_alcn = path.meta_info['parent_alcn'] || 146 (path.parent_path == '' ? '' : Webgen::Path.new(path.parent_path).alcn) 147 if !(parent = @website.tree[parent_alcn]) 148 raise Webgen::NodeCreationError.new("The needed parent node <#{parent_alcn}> does not exist") 149 end 150 parent 151 end
Private Instance Methods
Consider the number index
to be 1-based and convert it to a 0-based index needed for Ruby arrays.
An error is raised if the index is equal to 0.
# File lib/webgen/path_handler/base.rb 248 def adjust_index(index) 249 if index > 0 250 index - 1 251 elsif index == 0 252 raise Webgen::NodeCreationError.new("Invalid meta info 'dest_path', index into parent segments must not be 0") 253 else 254 index 255 end 256 end
Construct the destination path from the parent node and the path.
# File lib/webgen/path_handler/base.rb 176 def construct_dest_path(parent, path, force_lang_part) 177 unless path.meta_info['dest_path'].kind_of?(String) 178 raise Webgen::NodeCreationError.new("Invalid meta info 'dest_path', must be a string") 179 end 180 dest_path = path.meta_info['dest_path'].dup 181 182 if dest_path.start_with?('webgen:') 183 dest_path.gsub!(/^webgen:/, '') 184 elsif dest_path !~ /^[\w+.-]+:/ 185 parent = parent.parent while parent.is_fragment? 186 parent_segments = parent.dest_path.split('/')[1..-1] || [] 187 use_lang_part = if path.meta_info['lang'].nil? # unlocalized files never get a lang in the filename! 188 false 189 elsif force_lang_part 190 true 191 elsif @website.config['path_handler.lang_code_in_dest_path'] == 'except_default' 192 @website.config['website.lang'] != path.meta_info['lang'] 193 else 194 @website.config['path_handler.lang_code_in_dest_path'] 195 end 196 use_version_part = if @website.config['path_handler.version_in_dest_path'] == 'except_default' 197 path.meta_info['version'] != 'default' 198 else 199 @website.config['path_handler.version_in_dest_path'] 200 end 201 202 replace_segment = lambda do |match| 203 case match 204 when DEST_PATH_PARENT_SEGMENTS 205 nr1 = adjust_index($1.to_i) 206 (nr2 = adjust_index($2.to_i)) if $2 207 [parent_segments[nr2 ? nr1..nr2 : nr1]].flatten.compact.join('/') 208 when "<parent>" 209 parent.dest_path 210 when "<basename>" 211 path.basename 212 when "<ext>" 213 path.ext.empty? ? '' : '.' << path.ext 214 when "<lang>" 215 use_lang_part ? path.meta_info['lang'] : '' 216 when "<version>" 217 use_version_part ? path.meta_info['version'] : '' 218 when "<modified_at>" 219 path.meta_info['modified_at_in_dest_path'] ? path.meta_info['modified_at'].strftime('%Y%m%d%H%M%S') : '' 220 when /<(year|month|day)>/ 221 ctime = path.meta_info['created_at'] 222 if !ctime.kind_of?(Time) 223 raise Webgen::NodeCreationError.new("Invalid meta info 'created_at', needed for destination path creation") 224 end 225 ctime.send($1).to_s.rjust(2, '0') 226 when /\((.*)\)/ 227 inner = $1 228 replaced = inner.gsub(DEST_PATH_SEGMENTS, &replace_segment) 229 removed = inner.gsub(DEST_PATH_SEGMENTS, "") 230 replaced == removed ? '' : replaced 231 else 232 raise Webgen::NodeCreationError.new("Unknown destination path segment name: #{match}") 233 end 234 end 235 dest_path.gsub!(DEST_PATH_SEGMENTS, &replace_segment) 236 dest_path += '/' if path.path =~ /\/$/ 237 dest_path.gsub!(/\/\/+/, '/') 238 end 239 240 dest_path 241 end