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

path[R]

The original path string from which this Path object was created.

Public Class Methods

absolute?(uri) click to toggle source

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(base, path) click to toggle source

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
lcn(cn, lang) click to toggle source

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
matches_pattern?(path, pattern, options = File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME) click to toggle source

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
new(path, meta_info = {}, &ioblock) click to toggle source

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
url(path, make_absolute = true) click to toggle source

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

<=>(other) click to toggle source

Compare the path of this object to 'other.path'.

    # File lib/webgen/path.rb
277 def <=>(other)
278   @path <=> other.to_str
279 end
==(other) click to toggle source

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
Also aliased as: eql?
[](key) click to toggle source

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
[]=(key, value) click to toggle source

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
acn() click to toggle source

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
alcn() click to toggle source

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
basename() click to toggle source

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
cn() click to toggle source

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
data(mode = nil) click to toggle source

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
eql?(other)
Alias for: ==
ext() click to toggle source

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
ext=(value) click to toggle source

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
io(mode = 'r') { |io| ... } click to toggle source

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
lcn() click to toggle source

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_info() click to toggle source

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_at(mp, prefix = nil) click to toggle source

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
parent_path() click to toggle source

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_io(&block) click to toggle source

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() click to toggle source

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_directory() click to toggle source

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_file() click to toggle source

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_fragment() click to toggle source

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
custom_cn() click to toggle source

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
use_version_for_cn?() click to toggle source

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