# -*- encoding: utf-8 -*-
require 'ostruct'
require 'fileutils'
require 'webgen/website'
module Webgen
# This class is used for managing webgen websites. It provides access to website templates and
# styles defined as resources and makes it easy to apply them to a webgen website.
#
# = General information
#
# Currently, the following actions are supported:
#
# * creating a website based on a website template (#create_website)
# * applying a template to an existing website (#apply_template)
# * applying a style to an existing website (#apply_style)
#
# A website template defines some initial pages which should be filled with real data. For
# example, the @project@ template defines several pages which are useful for software projects
# including a features and about page.
#
# A style defines, for example, the basic page layout (in the case of website styles) or how image
# galleries should look like (in the case of gallery styles). So styles are basically used to
# change the appearance of parts (or the whole) website. This makes them a powerful tool as this
# plugin makes it easy to change a style later!
#
# = website template and style resource naming convention
#
# Styles and website templates are defined using resources. Each such resource has to be a
# directory containing an optional README file in YAML format in which key-value pairs provide
# additional information about the style or website template. All other files/directories in the
# directory are copied to the root of the destination webgen website when the style or website
# template is used.
#
# This class uses a special naming convention to recognize website templates and styles:
#
# * A resource named webgen-website-template-TEMPLATE_NAME is considered to be a website
# template called TEMPLATE_NAME and can be later accessed using this name.
#
# * A resource named webgen-website-style-CATEGORY-STYLE_NAME is considered to be a style
# in the category CATEGORY called STYLE_NAME. There are no fixed categories, one can use
# anything here! Again, the style can later be accessed by providing the category and style
# name.
#
# Website template names have to be unique and style names have to be unique in respect to their
# categories!
#
# Note: All styles without a category or which are in the category 'website' are website styles.
class WebsiteManager
# A hash with the available website templates (mapping name to infos).
attr_reader :templates
# A hash with the available website styles (mapping name to infos).
attr_reader :styles
# The used Website object.
attr_reader :website
# Create a new WebsiteManager for the website +dir+.
def initialize(dir)
@website = Webgen::Website.new(dir)
@website.init
@styles = {}
@templates = {}
@website.execute_in_env do
[['webgen-website-style-', @styles], ['webgen-website-template-', @templates]].each do |prefix, var|
@website.config['resources'].select {|name, data| name =~ /^#{prefix}/}.each do |name, data|
paths = Webgen::Source::Resource.new(name).paths
readme = paths.select {|path| path == '/README' }.first
paths.delete(readme) if readme
infos = OpenStruct.new(readme.nil? ? {} : YAML::load(readme.io.data))
infos.paths = paths
var[name.sub(prefix, '')] = infos
end
end
end
end
# Create the basic website skeleton (without any template or style applied).
def create_website
raise "Directory <#{@website.directory}> does already exist!" if File.exists?(@website.directory)
@website.execute_in_env { write_paths(Webgen::Source::Resource.new('webgen-website-skeleton').paths) }
end
# Apply the given +template+ to the website by copying the template files.
def apply_template(name)
write_paths_to_website(@templates[name], 'template')
end
# Apply the given website style +name+ to the website by copying the styles files.
def apply_style(name)
write_paths_to_website(@styles[name], 'style')
end
#######
private
#######
# Do some sanity checks and write the +paths+ from +infos+ to the website directory.
def write_paths_to_website(infos, infos_type)
raise ArgumentError.new("Invalid #{infos_type} name") if infos.nil?
raise "Directory <#{@website.directory}> does not exist!" unless File.exists?(@website.directory)
write_paths(infos.paths)
end
# Write the paths to the website directory.
def write_paths(paths)
paths.each do |path|
output_path = File.join(@website.directory, path.path)
if path.path =~ /\/$/
FileUtils.mkdir_p(output_path)
else
FileUtils.mkdir_p(File.dirname(output_path))
path.io.stream do |source|
File.open(output_path, 'wb') {|f| FileUtils.copy_stream(source, f) }
end
end
end
end
end
end