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