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, line 72 def initialize(website) @website = website 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, line 84 def parse_meta_info!(path) [] 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, line 110 def create_node(path) return nil if path.meta_info['draft'] parent = parent_node(path) dest_path = self.dest_path(parent, path) if node = node_exists?(path, dest_path) node_path = node.node_info[:path] if node_path != path raise Webgen::NodeCreationError.new("Another node <#{node}> with the same alcn or destination path already exists") elsif node_path.meta_info == path.meta_info @website.blackboard.dispatch_msg(:reused_existing_node, node) return node else node.tree.delete_node(node) end end if !path.meta_info['modified_at'].kind_of?(Time) @website.logger.debug do "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}" end path.meta_info['modified_at'] = Time.now end node = node_class(path).new(parent, path.cn, dest_path, path.meta_info.dup) node.node_info[:path] = path node.node_info[:path_handler] = self yield(node) if block_given? node 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, line 162 def dest_path(parent, path) path.meta_info['dest_path'] ||= '<parent><basename>(-<version>)(-<modified_at>)(.<lang>)<ext>' dpath = construct_dest_path(parent, path, false) if (node = node_exists?(path, dpath)) && node.lang != path.meta_info['lang'] dpath = construct_dest_path(parent, path, true) end dpath end
Retrieve the node class that should be used for the given path.
# File lib/webgen/path_handler/base.rb, line 267 def node_class(path) if String === (klass = path.meta_info['node_class']) Webgen::Utils.const_for_name(klass) rescue Node elsif String === (klass = path.meta_info['base_node_class']) Webgen::Utils.const_for_name(klass) rescue Node else Node end 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, line 261 def node_exists?(path, dest_path) @website.tree[path.alcn] || (!path.meta_info['no_output'] && @website.tree.node(dest_path, :dest_path)) end
Return the parent node for the given path.
# File lib/webgen/path_handler/base.rb, line 144 def parent_node(path) parent_alcn = path.meta_info['parent_alcn'] || (path.parent_path == '' ? '' : Webgen::Path.new(path.parent_path).alcn) if !(parent = @website.tree[parent_alcn]) raise Webgen::NodeCreationError.new("The needed parent node <#{parent_alcn}> does not exist") end parent 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, line 248 def adjust_index(index) if index > 0 index - 1 elsif index == 0 raise Webgen::NodeCreationError.new("Invalid meta info 'dest_path', index into parent segments must not be 0") else index end end
Construct the destination path from the parent node and the path.
# File lib/webgen/path_handler/base.rb, line 176 def construct_dest_path(parent, path, force_lang_part) unless path.meta_info['dest_path'].kind_of?(String) raise Webgen::NodeCreationError.new("Invalid meta info 'dest_path', must be a string") end dest_path = path.meta_info['dest_path'].dup if dest_path.start_with?('webgen:') dest_path.gsub!(/^webgen:/, '') elsif dest_path !~ /^[\w+.-]+:/ parent = parent.parent while parent.is_fragment? parent_segments = parent.dest_path.split('/')[1..-1] || [] use_lang_part = if path.meta_info['lang'].nil? # unlocalized files never get a lang in the filename! false elsif force_lang_part true elsif @website.config['path_handler.lang_code_in_dest_path'] == 'except_default' @website.config['website.lang'] != path.meta_info['lang'] else @website.config['path_handler.lang_code_in_dest_path'] end use_version_part = if @website.config['path_handler.version_in_dest_path'] == 'except_default' path.meta_info['version'] != 'default' else @website.config['path_handler.version_in_dest_path'] end replace_segment = lambda do |match| case match when DEST_PATH_PARENT_SEGMENTS nr1 = adjust_index($1.to_i) (nr2 = adjust_index($2.to_i)) if $2 [parent_segments[nr2 ? nr1..nr2 : nr1]].flatten.compact.join('/') when "<parent>" parent.dest_path when "<basename>" path.basename when "<ext>" path.ext.empty? ? '' : '.' << path.ext when "<lang>" use_lang_part ? path.meta_info['lang'] : '' when "<version>" use_version_part ? path.meta_info['version'] : '' when "<modified_at>" path.meta_info['modified_at_in_dest_path'] ? path.meta_info['modified_at'].strftime('%Y%m%d%H%M%S') : '' when /<(year|month|day)>/ ctime = path.meta_info['created_at'] if !ctime.kind_of?(Time) raise Webgen::NodeCreationError.new("Invalid meta info 'created_at', needed for destination path creation") end ctime.send($1).to_s.rjust(2, '0') when /\((.*)\)/ inner = $1 replaced = inner.gsub(DEST_PATH_SEGMENTS, &replace_segment) removed = inner.gsub(DEST_PATH_SEGMENTS, "") replaced == removed ? '' : replaced else raise Webgen::NodeCreationError.new("Unknown destination path segment name: #{match}") end end dest_path.gsub!(DEST_PATH_SEGMENTS, &replace_segment) dest_path += '/' if path.path =~ /\/$/ dest_path.gsub!(/\/\/+/, '/') end dest_path end