class Webgen::Path
About¶ ↑
A Path
object provides information about a path that is used to create one or more nodes as well as methods for accessing/modifying the path's content. Path
objects are created by Source
classes but can also be created during the rendering phase (see PathHandler#create_secondary_nodes
).
So a Path
object always refers to a path from which nodes are created! In contrast, destination paths are just strings and specify the location where a specific node should be written to (see Node#destination_path).
A Path
object can represent one of three different things: a directory, a file or a fragment. If the path
ends with a slash character, then the path object represents a directory, if the path contains a hash character anywhere, then the path object represents a fragment and else it represents a file. Have a look at the user documentation to see the exact format that can be used for a path string!
Utility methods¶ ↑
The Path
class also provides some general methods for working with path strings which are also used, for example, by the Node
class:
Attributes
The original path string from which this Path
object was created.
Public Class Methods
Return true
if the given URI is an absolute one, i.e. if it include a scheme.
# File lib/webgen/path.rb 59 def self.absolute?(uri) 60 uri =~ /\A[\w+.-]+:/ 61 end
Append the path
to the base
path.
-
The
base
parameter has to be an acn/alcn/absolute path (i.e. starting with a slash). -
If
base
represents a directory, it needs to have a trailing slash! -
The
path
parameter doesn't need to be absolute and may contain path patterns.
# File lib/webgen/path.rb 68 def self.append(base, path) 69 result = url(base) + url(path, false) 70 (result.fragment.nil? ? result.path : "#{result.path}##{result.fragment}").encode!(path.encoding) 71 end
Construct a localized canonical name from a given canonical name and a language.
# File lib/webgen/path.rb 87 def self.lcn(cn, lang) 88 if lang.nil? 89 cn 90 else 91 cn.split('.').insert((cn.start_with?('.') ? 2 : 1), lang.to_s).join('.') 92 end 93 end
Return true
if the given path string matches the given non-empty path pattern.
If a fragment path (i.e. one which has a hash character somewhere) should be matched, the pattern needs to have a hash character as well.
For information on which patterns are supported, have a look at the API documentation of File.fnmatch.
# File lib/webgen/path.rb 80 def self.matches_pattern?(path, pattern, options = File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME) 81 path = path.to_s 82 pattern += '/' if path[-1] == ?/ && pattern[-1] != ?/ 83 (path.include?('#') ? pattern.include?('#') : true) && File.fnmatch(pattern, path, options) 84 end
Create a new Path
object for path
(a string).
The optional block needs to return an IO object for getting the content of the path (see io
and data
).
The path
string needs to be in a well defined format which can be looked up in the webgen user documentation.
# File lib/webgen/path.rb 105 def initialize(path, meta_info = {}, &ioblock) 106 @path = path.freeze 107 @meta_info = meta_info.dup 108 @ioblock = block_given? ? ioblock : nil 109 end
Construct an internal URL for the given path
.
If the parameter make_absolute
is true
, then the path will be made absolute by prepending the special URL 'webgen://lh'
# File lib/webgen/path.rb 47 def self.url(path, make_absolute = true) 48 URL_CACHE[[path, make_absolute]] ||= begin 49 if absolute?(path) || !make_absolute 50 URI.parse(URI::DEFAULT_PARSER.escape(path, URL_UNSAFE_PATTERN)) 51 else 52 URI.parse(URI::DEFAULT_PARSER.escape("webgen://lh#{path[0] != ?/ ? '/' : ''}#{path}", 53 URL_UNSAFE_PATTERN)) 54 end 55 end.freeze 56 end
Public Instance Methods
Compare the path
of this object to 'other.path'.
# File lib/webgen/path.rb 277 def <=>(other) 278 @path <=> other.to_str 279 end
Equality – Return true
if other
is a Path
object with the same path
or if other
is a String equal to the path
. Else return false
.
# File lib/webgen/path.rb 265 def ==(other) 266 if other.kind_of?(Path) 267 other.path == @path 268 elsif other.kind_of?(String) 269 other == @path 270 else 271 false 272 end 273 end
Get the value of the meta information key.
This method has to be used to get meta information without triggering analyzation of the path string!
# File lib/webgen/path.rb 131 def [](key) 132 @meta_info[key] 133 end
Set the meta information key
to value
.
This method has to be used to set meta information without triggering analyzation of the path string!
# File lib/webgen/path.rb 139 def []=(key, value) 140 @meta_info[key] = value 141 end
The absolute canonical name of this path.
Triggers analyzation of the path if invoked.
# File lib/webgen/path.rb 196 def acn 197 if @path.include?('#') 198 self.class.new(parent_path).acn << cn 199 else 200 parent_path + cn 201 end 202 end
The absolute localized canonical name of this path.
Triggers analyzation of the path if invoked.
# File lib/webgen/path.rb 207 def alcn 208 if @path.include?('#') 209 self.class.new(parent_path).alcn << lcn 210 else 211 parent_path + lcn 212 end 213 end
The canonical name of the path without the extension.
Triggers analyzation of the path if invoked.
# File lib/webgen/path.rb 153 def basename 154 defined?(@basename) ? @basename : (analyse; @basename) 155 end
The canonical name created from the path
(namely from the parts basename
and extension
as well as the meta information version
).
Triggers analyzation of the path if invoked.
# File lib/webgen/path.rb 176 def cn 177 if meta_info['cn'] 178 tmp_cn = custom_cn 179 else 180 tmp_cn = basename.dup << (use_version_for_cn? ? "-#{meta_info['version']}" : '') << 181 (ext.length > 0 ? ".#{ext}" : '') 182 end 183 tmp_cn << (@path =~ /.\/$/ ? '/' : '') 184 end
Return the content of the IO object of the path as string.
For a description of the parameter mode
see io
.
An error is raised, if no IO object is associated with the Path
instance.
# File lib/webgen/path.rb 253 def data(mode = nil) 254 mode ||= @meta_info['io_open_mode'] || 'r' 255 io(mode) {|io| io.read} 256 end
The extension of the path.
Triggers analyzation of the path if invoked.
# File lib/webgen/path.rb 160 def ext 161 defined?(@ext) ? @ext : (analyse; @ext) 162 end
Set the extension of the path.
Triggers analyzation of the path if invoked.
# File lib/webgen/path.rb 167 def ext=(value) 168 defined?(@ext) || analyse 169 @ext = value 170 end
Provide access to the IO object of the path by yielding it.
After the method block returns, the IO object is automatically closed. An error is raised, if no IO object is associated with the Path
instance.
The parameter mode
specifies the mode in which the IO object should be opened. This can be used, for example, to specify a certain input encoding or to use binary mode.
# File lib/webgen/path.rb 240 def io(mode = 'r') # :yields: io 241 raise "No IO object defined for the path #{self}" if @ioblock.nil? 242 io = @ioblock.call(mode) 243 yield(io) 244 ensure 245 io.close if io 246 end
The localized canonical name created from the path
.
Triggers analyzation of the path if invoked.
# File lib/webgen/path.rb 189 def lcn 190 self.class.lcn(cn, meta_info['lang']) 191 end
Meta information about the path.
Triggers analyzation of the path if invoked. See []=
to setting meta information without triggering analyzation.
# File lib/webgen/path.rb 123 def meta_info 124 defined?(@basename) ? @meta_info : (analyse; @meta_info) 125 end
Mount this path at the mount point mp
, optionally stripping prefix
from the parent path, and return the new Path
object.
The parameters mp
and prefix
have to be absolute directory paths, ie. they have to start and end with a slash and must not contain any hash characters!
Also note that mounting a path is not possible once it is fully initialized, i.e. once some information extracted from the path string is accessed.
# File lib/webgen/path.rb 224 def mount_at(mp, prefix = nil) 225 raise(ArgumentError, "Can't mount a fully initialized path") if defined?(@basename) 226 raise(ArgumentError, "The mount point (#{mp}) must be a valid directory path") if mp =~ /^[^\/]|#|[^\/]$/ 227 raise(ArgumentError, "The strip prefix (#{prefix}) must be a valid directory path") if !prefix.nil? && prefix =~ /^[^\/]|#|[^\/]$/ 228 229 temp = self.class.new(File.join(mp, @path.sub(/^#{Regexp.escape(prefix.to_s)}/, '')), @meta_info, &@ioblock) 230 temp 231 end
The string specifying the parent path.
Triggers analyzation of the path if invoked.
# File lib/webgen/path.rb 146 def parent_path 147 defined?(@parent_path) ? @parent_path : (analyse; @parent_path) 148 end
Set the IO block to the provided block.
# File lib/webgen/path.rb 259 def set_io(&block) 260 @ioblock = block 261 end
Private Instance Methods
Analyse the path and extract the needed information.
# File lib/webgen/path.rb 299 def analyse 300 if @path.include?('#') 301 analyse_fragment 302 elsif @path[-1] == ?/ 303 analyse_directory 304 else 305 analyse_file 306 end 307 @meta_info['title'] ||= begin 308 name = @basename.tr('_-', ' ') 309 name[0] = name[0].upcase 310 name 311 end 312 @ext ||= '' 313 raise "The basename of a path may not be empty: #{@path}" if @basename.empty? || @basename == '#' 314 raise "The parent path must start with a slash: #{@path}" if @path[0] != ?/ 315 end
Analyse the path assuming it is a directory.
# File lib/webgen/path.rb 318 def analyse_directory 319 @parent_path = (@path == '/' ? '' : File.join(File.dirname(@path), '/')) 320 @basename = File.basename(@path) 321 end
Analyse the path assuming it is a file.
# File lib/webgen/path.rb 326 def analyse_file 327 @parent_path = File.join(File.dirname(@path), '/') 328 match_data = FILENAME_RE.match(File.basename(@path)) 329 330 if !match_data[1].nil? && match_data[3].nil? && match_data[4].nil? 331 # handle special case of sort_info.basename as basename.ext 332 @basename = match_data[1] 333 @ext = match_data[2] 334 elsif !match_data[1].nil? && match_data[3].nil? && !match_data[4].nil? && 335 (lang = Webgen::LanguageManager.language_for_code(match_data[2])) 336 # handle special case of sort_info.basename.ext as basename.lang.ext if basename is a lang 337 @basename = match_data[1] 338 @meta_info['lang'] = lang 339 @ext = match_data[4] 340 else 341 @meta_info['sort_info'] ||= match_data[1].to_i unless match_data[1].nil? 342 @basename = match_data[2] 343 @meta_info['lang'] ||= Webgen::LanguageManager.language_for_code(match_data[3]) if match_data[3] 344 @ext = (@meta_info['lang'].nil? && !match_data[3].nil? ? match_data[3] << '.' : '') << match_data[4].to_s 345 end 346 end
Analyse the path assuming it is a fragment.
# File lib/webgen/path.rb 349 def analyse_fragment 350 @parent_path, @basename = @path.scan(/^(.*?)(#.*?)$/).first 351 raise "The parent path of a fragment path must be a file path and not a directory path: #{@path}" if @parent_path[-1] == ?/ 352 raise "A fragment path must only contain one hash character: #{path}" if @path.count("#") > 1 353 end
Construct a custom canonical name given by the 'cn' meta information.
# File lib/webgen/path.rb 363 def custom_cn 364 replace_segment = lambda do |match| 365 case match 366 when "<basename>" 367 basename 368 when "<ext>" 369 ext.empty? ? '' : '.' << ext 370 when "<version>" 371 use_version_for_cn? ? meta_info['version'] : '' 372 when /\((.*)\)/ 373 inner = $1 374 replaced = inner.gsub(CN_SEGMENTS, &replace_segment) 375 removed = inner.gsub(CN_SEGMENTS, "") 376 replaced == removed ? '' : replaced 377 else 378 '' 379 end 380 end 381 self.meta_info['cn'].to_s.gsub(CN_SEGMENTS, &replace_segment).gsub(/\/+$/, '') 382 end
Whether the version information should be added to the cn?
# File lib/webgen/path.rb 356 def use_version_for_cn? 357 meta_info['version'] && meta_info['version'] != 'default' 358 end