lib/webgen/source.rb in webgen-0.5.17 vs lib/webgen/source.rb in webgen-1.0.0.beta1
- old
+ new
@@ -1,57 +1,139 @@
# -*- encoding: utf-8 -*-
+require 'webgen/extension_manager'
+require 'webgen/path'
+
module Webgen
# Namespace for all classes that provide source paths.
#
- # == Implementing a source class
+ # == About
#
- # Source classes provide access to the source paths on which the source handlers act.
+ # This class is used to manage source classes. A source class is a class that returns a set of
+ # Path objects when the \#paths method is called. For example, the FileSystem class uses the file
+ # system as the source for the source paths.
#
- # A source class only needs to respond to the method +paths+ which needs to return a set of paths
- # for the source. The returned paths must respond to the method <tt>changed?</tt> (has to return
- # +true+ if the paths has changed since the last webgen run). If a path represents a directory, it
- # needs to have a trailing slash! The default implementation in the Path class just returns
- # +true+. One can either derive a specialized path class or define singleton methods on each path
- # object.
+ # The #register method is used for registering new source classes.
#
- # Also note that the returned Path objects should have the meta information <tt>modified_at</tt>
- # set to the correct last modification time of the path, ie. the value has to be a Time object!
+ # To get all configured source paths, use the #paths method of this class.
#
- # == Sample Source Class
+ # Extension writers may be interested in the #passive_sources accessor which allows one to
+ # register sources that provide paths that are only used when actually referenced.
#
- # Following is a simple source class which has stored the paths and their contents in a hash:
+ # == Implementing a source class
#
+ # A source class only needs to respond to the method +paths+ which needs to return a set of Path
+ # objects for the source. It is expected that after a source object is initialized it always
+ # returns the same path objects. The +initialize+ method of a source class must take the website
+ # object as first argument and may take an arbitrary number of additional arguments.
+ #
+ # Note that the returned Path objects need to have the meta information 'modified_at' set to the
+ # correct last modification time of the path, i.e. the value has to be a Time object! This is
+ # needed to determine whether the content of the path has been changed since the last invocation
+ # of webgen.
+ #
+ # == Sample source class
+ #
+ # Following is a simple source class which stores the paths and their contents in a hash:
+ #
# require 'stringio'
+ # require 'set'
+ # require 'webgen/path'
#
# class MemorySource
#
# CONTENT = {
# '/directory/' => nil,
# '/directory/file.page' => "This is the content of the file"
# }
#
+ # def initialize(website, data = {})
+ # @data = data
+ # end
+ #
# def paths
- # CONTENT.collect do |path, content|
- # Webgen::Path.new(path) { StringIO.new(content.to_s) }
+ # CONTENT.merge(@data).collect do |path, content|
+ # Webgen::Path.new(path, 'modified_at' => Time.now) { StringIO.new(content.to_s) }
# end.to_set
# end
#
# end
#
- # You can use this source class in your website (after placing the code in, for example,
- # <tt>ext/init.rb</tt>) by updating the <tt>sources</tt> configuration option:
+ # website.ext.source.register MemorySource, :name => 'memory'
#
- # WebsiteAccess.website.config['sources'] << ['/', 'MemorySource']
- #
- module Source
+ class Source
- autoload :Base, 'webgen/source/base'
- autoload :FileSystem, 'webgen/source/filesystem'
- autoload :Stacked, 'webgen/source/stacked'
- autoload :Resource, 'webgen/source/resource'
- autoload :TarArchive, 'webgen/source/tararchive'
+ include Webgen::ExtensionManager
+
+
+ # An array with one or more passive source definitions (a source definition is an array
+ # containing a mount point, the short name for a Source class and its arguments).
+ #
+ # The paths read from these sources will automatically be tagged with the 'passive' meta
+ # information key so that they are only used when referenced.
+ #
+ # This is very useful for providing templates, images and other paths in webgen extensions that
+ # should only be rendered when actually being referenced.
+ attr_reader :passive_sources
+
+
+ # Create a new source manager object for the given website.
+ def initialize(website)
+ super()
+ @website = website
+ @passive_sources = []
+ end
+
+ # Register a source class.
+ #
+ # The parameter +klass+ has to contain the name of the source class or the class object itself.
+ # If the class is located under this namespace, only the class name without the hierarchy part
+ # is needed, otherwise the full class name including parent module/class names is needed.
+ #
+ # === Options:
+ #
+ # [:name] The name for the source. If not set, it defaults to the snake-case version (i.e.
+ # FileSystem → file_system) of the class name (without the hierarchy part). It should
+ # only contain letters.
+ #
+ # === Examples:
+ #
+ # source.register('FileSystem') # registers Webgen::Source::FileSystem
+ #
+ # source.register('::FileSystem') # registers FileSystem !!!
+ #
+ # source.register('MyModule::Doit', name: 'my_doit')
+ #
+ def register(klass, options={}, &block)
+ do_register(klass, options, false, &block)
+ end
+
+ # Return all configured source paths.
+ #
+ # The source paths are taken from the sources specified in the "sources" configuration option
+ # and from passive sources array (see #passive_sources). All paths that additionally match one
+ # of the "sources.ignore_paths" patterns are ignored.
+ def paths
+ if !defined?(@paths)
+ active_source = extension('stacked').new(@website, @website.config['sources'].collect do |mp, name, *args|
+ [mp, extension(name).new(@website, *args)]
+ end)
+ passive_source = extension('stacked').new(@website, @passive_sources.collect do |mp, name, *args|
+ [mp, extension(name).new(@website, *args)]
+ end)
+ passive_source.paths.each {|path| path['passive'] = true}
+ source = extension('stacked').new(@website, [['/', active_source], ['/', passive_source]])
+
+ @paths = []
+ source.paths.each do |path|
+ if !(@website.config['sources.ignore_paths'].any? {|pat| Webgen::Path.matches_pattern?(path, pat)})
+ @paths << path
+ end
+ end
+ end
+ @paths
+ end
end
end