Class: Webgen::Path

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/webgen/path.rb

Overview

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:

  • Path.url

  • Path.append

  • Path.matches_pattern?

  • Path.lcn

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 so that paths with fragments work correctly.

Regexp.new("[^#{URI::PATTERN::UNRESERVED}#{URI::PATTERN::RESERVED}#]")
URL_CACHE =

Hash that caches generated URLs

{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, meta_info = {}, &ioblock) ⇒ Path

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.



106
107
108
109
110
# File 'lib/webgen/path.rb', line 106

def initialize(path, meta_info = {}, &ioblock)
  @path = path.freeze
  @meta_info = meta_info.dup
  @ioblock = block_given? ? ioblock : nil
end

Instance Attribute Details

#pathObject (readonly)

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



118
119
120
# File 'lib/webgen/path.rb', line 118

def path
  @path
end

Class Method Details

.absolute?(uri) ⇒ Boolean

Return true if the given URI is an absolute one, i.e. if it include a scheme.

Returns:

  • (Boolean)


60
61
62
# File 'lib/webgen/path.rb', line 60

def self.absolute?(uri)
  uri =~ /\A[\w+.-]+:/
end

.append(base, path) ⇒ Object

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.



69
70
71
72
# File 'lib/webgen/path.rb', line 69

def self.append(base, path)
  result = url(base) + url(path, false)
  (result.fragment.nil? ? result.path : "#{result.path}##{result.fragment}").encode!(path.encoding)
end

.lcn(cn, lang) ⇒ Object

Construct a localized canonical name from a given canonical name and a language.



88
89
90
91
92
93
94
# File 'lib/webgen/path.rb', line 88

def self.lcn(cn, lang)
  if lang.nil?
    cn
  else
    cn.split('.').insert((cn.start_with?('.') ? 2 : 1), lang.to_s).join('.')
  end
end

.matches_pattern?(path, pattern, options = File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME) ⇒ Boolean

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.

Returns:

  • (Boolean)


81
82
83
84
85
# File 'lib/webgen/path.rb', line 81

def self.matches_pattern?(path, pattern, options = File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
  path = path.to_s
  pattern += '/' if path[-1] == ?/ && pattern[-1] != ?/
  (path.include?('#') ? pattern.include?('#') : true) && File.fnmatch(pattern, path, options)
end

.url(path, make_absolute = true) ⇒ Object

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’



48
49
50
51
52
53
54
55
56
57
# File 'lib/webgen/path.rb', line 48

def self.url(path, make_absolute = true)
  URL_CACHE[[path, make_absolute]] ||= begin
                                         if absolute?(path) || !make_absolute
                                           URI.parse(URI::DEFAULT_PARSER.escape(path, URL_UNSAFE_PATTERN))
                                         else
                                           URI.parse(URI::DEFAULT_PARSER.escape("webgen://lh#{path[0] != ?/ ? '/' : ''}#{path}",
                                                                                URL_UNSAFE_PATTERN))
                                         end
                                       end.freeze
end

Instance Method Details

#<=>(other) ⇒ Object

Compare the #path of this object to ‘other.path’.



278
279
280
# File 'lib/webgen/path.rb', line 278

def <=>(other)
  @path <=> other.to_str
end

#==(other) ⇒ Object Also known as: eql?

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.



266
267
268
269
270
271
272
273
274
# File 'lib/webgen/path.rb', line 266

def ==(other)
  if other.kind_of?(Path)
    other.path == @path
  elsif other.kind_of?(String)
    other == @path
  else
    false
  end
end

#[](key) ⇒ Object

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!



132
133
134
# File 'lib/webgen/path.rb', line 132

def [](key)
  @meta_info[key]
end

#[]=(key, value) ⇒ Object

Set the meta information key to value.

This method has to be used to set meta information without triggering analyzation of the path string!



140
141
142
# File 'lib/webgen/path.rb', line 140

def []=(key, value)
  @meta_info[key] = value
end

#acnObject

The absolute canonical name of this path.

Triggers analyzation of the path if invoked.



197
198
199
200
201
202
203
# File 'lib/webgen/path.rb', line 197

def acn
  if @path.include?('#')
    self.class.new(parent_path).acn << cn
  else
    parent_path + cn
  end
end

#alcnObject

The absolute localized canonical name of this path.

Triggers analyzation of the path if invoked.



208
209
210
211
212
213
214
# File 'lib/webgen/path.rb', line 208

def alcn
  if @path.include?('#')
    self.class.new(parent_path).alcn << lcn
  else
    parent_path + lcn
  end
end

#basenameObject

The canonical name of the path without the extension.

Triggers analyzation of the path if invoked.



154
155
156
# File 'lib/webgen/path.rb', line 154

def basename
  defined?(@basename) ? @basename : (analyse; @basename)
end

#cnObject

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.



177
178
179
180
181
182
183
184
185
# File 'lib/webgen/path.rb', line 177

def cn
  if meta_info['cn']
    tmp_cn = custom_cn
  else
    tmp_cn = basename.dup << (use_version_for_cn? ? "-#{meta_info['version']}" : '') <<
      (ext.length > 0 ? ".#{ext}" : '')
  end
  tmp_cn << (@path =~ /.\/$/ ? '/' : '')
end

#data(mode = nil) ⇒ Object

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.



254
255
256
257
# File 'lib/webgen/path.rb', line 254

def data(mode = nil)
  mode ||= @meta_info['io_open_mode'] || 'r'
  io(mode) {|io| io.read}
end

#extObject

The extension of the path.

Triggers analyzation of the path if invoked.



161
162
163
# File 'lib/webgen/path.rb', line 161

def ext
  defined?(@ext) ? @ext : (analyse; @ext)
end

#ext=(value) ⇒ Object

Set the extension of the path.

Triggers analyzation of the path if invoked.



168
169
170
171
# File 'lib/webgen/path.rb', line 168

def ext=(value)
  defined?(@ext) || analyse
  @ext = value
end

#hashObject

:nodoc:



282
283
284
# File 'lib/webgen/path.rb', line 282

def hash #:nodoc:
  @path.hash
end

#initialize_copy(orig) ⇒ Object

:nodoc:



112
113
114
115
# File 'lib/webgen/path.rb', line 112

def initialize_copy(orig) #:nodoc:
  super
  @meta_info = orig.instance_variable_get(:@meta_info).dup
end

#inspectObject

:nodoc:



291
292
293
# File 'lib/webgen/path.rb', line 291

def inspect #:nodoc:
  "#<Path: #{@path}>"
end

#io(mode = 'r') ⇒ Object

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.



241
242
243
244
245
246
247
# File 'lib/webgen/path.rb', line 241

def io(mode = 'r') # :yields: io
  raise "No IO object defined for the path #{self}" if @ioblock.nil?
  io = @ioblock.call(mode)
  yield(io)
ensure
  io.close if io
end

#lcnObject

The localized canonical name created from the path.

Triggers analyzation of the path if invoked.



190
191
192
# File 'lib/webgen/path.rb', line 190

def lcn
  self.class.lcn(cn, meta_info['lang'])
end

#meta_infoObject

Meta information about the path.

Triggers analyzation of the path if invoked. See #[]= to setting meta information without triggering analyzation.



124
125
126
# File 'lib/webgen/path.rb', line 124

def meta_info
  defined?(@basename) ? @meta_info : (analyse; @meta_info)
end

#mount_at(mp, prefix = nil) ⇒ Object

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.

Raises:

  • (ArgumentError)


225
226
227
228
229
230
231
232
# File 'lib/webgen/path.rb', line 225

def mount_at(mp, prefix = nil)
  raise(ArgumentError, "Can't mount a fully initialized path") if defined?(@basename)
  raise(ArgumentError, "The mount point (#{mp}) must be a valid directory path") if mp =~ /^[^\/]|#|[^\/]$/
  raise(ArgumentError, "The strip prefix (#{prefix}) must be a valid directory path") if !prefix.nil? && prefix =~ /^[^\/]|#|[^\/]$/

  temp = self.class.new(File.join(mp, @path.sub(/^#{Regexp.escape(prefix.to_s)}/, '')), @meta_info, &@ioblock)
  temp
end

#parent_pathObject

The string specifying the parent path.

Triggers analyzation of the path if invoked.



147
148
149
# File 'lib/webgen/path.rb', line 147

def parent_path
  defined?(@parent_path) ? @parent_path : (analyse; @parent_path)
end

#set_io(&block) ⇒ Object

Set the IO block to the provided block.



260
261
262
# File 'lib/webgen/path.rb', line 260

def set_io(&block)
  @ioblock = block
end

#to_sObject Also known as: to_str

:nodoc:



286
287
288
# File 'lib/webgen/path.rb', line 286

def to_s #:nodoc:
  @path
end