gettalong-webgen 0.5.4.20080929
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/AUTHORS +5 -0
- data/COPYING +10 -0
- data/GPL +340 -0
- data/Rakefile +324 -0
- data/THANKS +17 -0
- data/bin/webgen +10 -0
- data/data/webgen/resources.yaml +3 -0
- data/data/webgen/webgui/controller/main.rb +129 -0
- data/data/webgen/webgui/overrides/win32console.rb +0 -0
- data/data/webgen/webgui/public/css/jquery.autocomplete.css +50 -0
- data/data/webgen/webgui/public/css/ramaze_error.css +90 -0
- data/data/webgen/webgui/public/css/style.css +55 -0
- data/data/webgen/webgui/public/img/headerbg.jpg +0 -0
- data/data/webgen/webgui/public/img/webgen_logo.png +0 -0
- data/data/webgen/webgui/public/js/jquery.autocomplete.js +15 -0
- data/data/webgen/webgui/public/js/jquery.js +32 -0
- data/data/webgen/webgui/view/create_website.xhtml +22 -0
- data/data/webgen/webgui/view/error.xhtml +64 -0
- data/data/webgen/webgui/view/index.xhtml +22 -0
- data/data/webgen/webgui/view/manage_website.xhtml +18 -0
- data/data/webgen/webgui/view/page.xhtml +40 -0
- data/data/webgen/website_skeleton/README +10 -0
- data/data/webgen/website_skeleton/Rakefile +40 -0
- data/data/webgen/website_skeleton/config.yaml +17 -0
- data/data/webgen/website_skeleton/ext/init.rb +6 -0
- data/data/webgen/website_styles/1024px/README +13 -0
- data/data/webgen/website_styles/1024px/src/default.css +188 -0
- data/data/webgen/website_styles/1024px/src/default.template +60 -0
- data/data/webgen/website_styles/1024px/src/images/background.gif +0 -0
- data/data/webgen/website_styles/andreas00/README +13 -0
- data/data/webgen/website_styles/andreas00/src/default.css +290 -0
- data/data/webgen/website_styles/andreas00/src/default.template +60 -0
- data/data/webgen/website_styles/andreas00/src/images/bg.gif +0 -0
- data/data/webgen/website_styles/andreas00/src/images/front.jpg +0 -0
- data/data/webgen/website_styles/andreas00/src/images/menubg.gif +0 -0
- data/data/webgen/website_styles/andreas00/src/images/menubg2.gif +0 -0
- data/data/webgen/website_styles/andreas01/README +14 -0
- data/data/webgen/website_styles/andreas01/src/default.css +310 -0
- data/data/webgen/website_styles/andreas01/src/default.template +61 -0
- data/data/webgen/website_styles/andreas01/src/images/bg.gif +0 -0
- data/data/webgen/website_styles/andreas01/src/images/front.jpg +0 -0
- data/data/webgen/website_styles/andreas01/src/print.css +35 -0
- data/data/webgen/website_styles/andreas03/README +14 -0
- data/data/webgen/website_styles/andreas03/src/default.css +223 -0
- data/data/webgen/website_styles/andreas03/src/default.template +58 -0
- data/data/webgen/website_styles/andreas03/src/images/bodybg.png +0 -0
- data/data/webgen/website_styles/andreas03/src/images/contbg.png +0 -0
- data/data/webgen/website_styles/andreas03/src/images/footerbg.png +0 -0
- data/data/webgen/website_styles/andreas03/src/images/gradient1.png +0 -0
- data/data/webgen/website_styles/andreas03/src/images/gradient2.png +0 -0
- data/data/webgen/website_styles/andreas04/README +15 -0
- data/data/webgen/website_styles/andreas04/src/default.css +290 -0
- data/data/webgen/website_styles/andreas04/src/default.template +81 -0
- data/data/webgen/website_styles/andreas04/src/images/blinkarrow.gif +0 -0
- data/data/webgen/website_styles/andreas04/src/images/bodybg.png +0 -0
- data/data/webgen/website_styles/andreas04/src/images/contentbg.png +0 -0
- data/data/webgen/website_styles/andreas04/src/images/entrybg.png +0 -0
- data/data/webgen/website_styles/andreas04/src/images/flash.gif +0 -0
- data/data/webgen/website_styles/andreas04/src/images/flash2.gif +0 -0
- data/data/webgen/website_styles/andreas04/src/images/globe.gif +0 -0
- data/data/webgen/website_styles/andreas04/src/images/globebottom.gif +0 -0
- data/data/webgen/website_styles/andreas04/src/images/linkarrow.gif +0 -0
- data/data/webgen/website_styles/andreas04/src/images/menuhover.png +0 -0
- data/data/webgen/website_styles/andreas05/README +14 -0
- data/data/webgen/website_styles/andreas05/src/default.css +33 -0
- data/data/webgen/website_styles/andreas05/src/default.template +40 -0
- data/data/webgen/website_styles/andreas05/src/images/bodybg.gif +0 -0
- data/data/webgen/website_styles/andreas05/src/images/front.png +0 -0
- data/data/webgen/website_styles/andreas06/README +14 -0
- data/data/webgen/website_styles/andreas06/src/default.css +354 -0
- data/data/webgen/website_styles/andreas06/src/default.template +70 -0
- data/data/webgen/website_styles/andreas06/src/images/bodybg.gif +0 -0
- data/data/webgen/website_styles/andreas06/src/images/boxbg.gif +0 -0
- data/data/webgen/website_styles/andreas06/src/images/greypx.gif +0 -0
- data/data/webgen/website_styles/andreas06/src/images/header.jpg +0 -0
- data/data/webgen/website_styles/andreas06/src/images/innerbg.gif +0 -0
- data/data/webgen/website_styles/andreas06/src/images/leaves.jpg +0 -0
- data/data/webgen/website_styles/andreas06/src/images/tabs.gif +0 -0
- data/data/webgen/website_styles/andreas07/README +15 -0
- data/data/webgen/website_styles/andreas07/src/browserfix.css +7 -0
- data/data/webgen/website_styles/andreas07/src/default.css +92 -0
- data/data/webgen/website_styles/andreas07/src/default.template +42 -0
- data/data/webgen/website_styles/andreas07/src/images/bodybg.gif +0 -0
- data/data/webgen/website_styles/andreas07/src/images/sidebarbg.gif +0 -0
- data/data/webgen/website_styles/andreas08/README +14 -0
- data/data/webgen/website_styles/andreas08/src/default.css +224 -0
- data/data/webgen/website_styles/andreas08/src/default.template +51 -0
- data/data/webgen/website_styles/andreas09/README +14 -0
- data/data/webgen/website_styles/andreas09/src/default.css +308 -0
- data/data/webgen/website_styles/andreas09/src/default.template +68 -0
- data/data/webgen/website_styles/andreas09/src/images/bodybg-black.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/bodybg-green.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/bodybg-orange.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/bodybg-purple.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/bodybg-red.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/bodybg.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/footerbg.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/menuhover-black.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/menuhover-green.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/menuhover-orange.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/menuhover-purple.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/menuhover-red.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/menuhover.jpg +0 -0
- data/data/webgen/website_styles/simple/README +6 -0
- data/data/webgen/website_styles/simple/src/default.css +84 -0
- data/data/webgen/website_styles/simple/src/default.template +36 -0
- data/data/webgen/website_templates/default/README +6 -0
- data/data/webgen/website_templates/default/src/index.page +8 -0
- data/data/webgen/website_templates/project/README +5 -0
- data/data/webgen/website_templates/project/src/about.page +12 -0
- data/data/webgen/website_templates/project/src/download.page +15 -0
- data/data/webgen/website_templates/project/src/features.page +8 -0
- data/data/webgen/website_templates/project/src/index.page +9 -0
- data/data/webgen/website_templates/project/src/screenshots.page +18 -0
- data/doc/contentprocessor.template +11 -0
- data/doc/contentprocessor/blocks.page +66 -0
- data/doc/contentprocessor/builder.page +80 -0
- data/doc/contentprocessor/erb.page +56 -0
- data/doc/contentprocessor/erubis.page +46 -0
- data/doc/contentprocessor/haml.page +47 -0
- data/doc/contentprocessor/maruku.page +41 -0
- data/doc/contentprocessor/rdiscount.page +37 -0
- data/doc/contentprocessor/rdoc.page +36 -0
- data/doc/contentprocessor/redcloth.page +39 -0
- data/doc/contentprocessor/sass.page +31 -0
- data/doc/contentprocessor/tags.page +73 -0
- data/doc/extensions.metainfo +29 -0
- data/doc/extensions.page +16 -0
- data/doc/extensions.template +17 -0
- data/doc/faq.page +214 -0
- data/doc/getting_started.page +134 -0
- data/doc/index.page +65 -0
- data/doc/manual.page +532 -0
- data/doc/reference_configuration.page +646 -0
- data/doc/reference_metainfo.page +213 -0
- data/doc/sourcehandler.template +21 -0
- data/doc/sourcehandler/copy.page +19 -0
- data/doc/sourcehandler/directory.page +27 -0
- data/doc/sourcehandler/feed.page +82 -0
- data/doc/sourcehandler/metainfo.page +41 -0
- data/doc/sourcehandler/page.page +30 -0
- data/doc/sourcehandler/sitemap.page +46 -0
- data/doc/sourcehandler/template.page +45 -0
- data/doc/sourcehandler/virtual.page +49 -0
- data/doc/tag.template +25 -0
- data/doc/tag/breadcrumbtrail.page +40 -0
- data/doc/tag/coderay.page +49 -0
- data/doc/tag/date.page +31 -0
- data/doc/tag/executecommand.page +26 -0
- data/doc/tag/includefile.page +32 -0
- data/doc/tag/langbar.page +22 -0
- data/doc/tag/menu.page +92 -0
- data/doc/tag/metainfo.page +29 -0
- data/doc/tag/relocatable.page +38 -0
- data/doc/tag/sitemap.page +31 -0
- data/doc/upgrading.page +139 -0
- data/doc/webgen_page_format.page +128 -0
- data/lib/webgen/blackboard.rb +73 -0
- data/lib/webgen/cache.rb +85 -0
- data/lib/webgen/cli.rb +118 -0
- data/lib/webgen/cli/create_command.rb +64 -0
- data/lib/webgen/cli/run_command.rb +20 -0
- data/lib/webgen/cli/utils.rb +86 -0
- data/lib/webgen/cli/webgui_command.rb +49 -0
- data/lib/webgen/common.rb +10 -0
- data/lib/webgen/common/sitemap.rb +76 -0
- data/lib/webgen/configuration.rb +147 -0
- data/lib/webgen/contentprocessor.rb +96 -0
- data/lib/webgen/contentprocessor/blocks.rb +46 -0
- data/lib/webgen/contentprocessor/builder.rb +26 -0
- data/lib/webgen/contentprocessor/context.rb +90 -0
- data/lib/webgen/contentprocessor/erb.rb +24 -0
- data/lib/webgen/contentprocessor/erubis.rb +40 -0
- data/lib/webgen/contentprocessor/haml.rb +25 -0
- data/lib/webgen/contentprocessor/maruku.rb +18 -0
- data/lib/webgen/contentprocessor/rdiscount.rb +15 -0
- data/lib/webgen/contentprocessor/rdoc.rb +17 -0
- data/lib/webgen/contentprocessor/redcloth.rb +15 -0
- data/lib/webgen/contentprocessor/sass.rb +18 -0
- data/lib/webgen/contentprocessor/tags.rb +134 -0
- data/lib/webgen/coreext.rb +10 -0
- data/lib/webgen/default_config.rb +198 -0
- data/lib/webgen/languages.rb +578 -0
- data/lib/webgen/loggable.rb +23 -0
- data/lib/webgen/logger.rb +78 -0
- data/lib/webgen/node.rb +347 -0
- data/lib/webgen/output.rb +37 -0
- data/lib/webgen/output/filesystem.rb +67 -0
- data/lib/webgen/page.rb +133 -0
- data/lib/webgen/path.rb +182 -0
- data/lib/webgen/source.rb +24 -0
- data/lib/webgen/source/filesystem.rb +58 -0
- data/lib/webgen/source/resource.rb +42 -0
- data/lib/webgen/source/stacked.rb +53 -0
- data/lib/webgen/sourcehandler.rb +202 -0
- data/lib/webgen/sourcehandler/base.rb +211 -0
- data/lib/webgen/sourcehandler/copy.rb +41 -0
- data/lib/webgen/sourcehandler/directory.rb +31 -0
- data/lib/webgen/sourcehandler/feed.rb +121 -0
- data/lib/webgen/sourcehandler/fragment.rb +71 -0
- data/lib/webgen/sourcehandler/metainfo.rb +117 -0
- data/lib/webgen/sourcehandler/page.rb +77 -0
- data/lib/webgen/sourcehandler/sitemap.rb +60 -0
- data/lib/webgen/sourcehandler/template.rb +68 -0
- data/lib/webgen/sourcehandler/virtual.rb +75 -0
- data/lib/webgen/tag.rb +23 -0
- data/lib/webgen/tag/base.rb +162 -0
- data/lib/webgen/tag/breadcrumbtrail.rb +71 -0
- data/lib/webgen/tag/coderay.rb +32 -0
- data/lib/webgen/tag/date.rb +18 -0
- data/lib/webgen/tag/executecommand.rb +29 -0
- data/lib/webgen/tag/includefile.rb +42 -0
- data/lib/webgen/tag/langbar.rb +52 -0
- data/lib/webgen/tag/menu.rb +186 -0
- data/lib/webgen/tag/metainfo.rb +25 -0
- data/lib/webgen/tag/relocatable.rb +53 -0
- data/lib/webgen/tag/sitemap.rb +42 -0
- data/lib/webgen/tree.rb +80 -0
- data/lib/webgen/version.rb +6 -0
- data/lib/webgen/webgentask.rb +148 -0
- data/lib/webgen/website.rb +214 -0
- data/lib/webgen/websiteaccess.rb +29 -0
- data/lib/webgen/websitemanager.rb +125 -0
- data/man/man1/webgen.1 +67 -0
- data/misc/default.css +360 -0
- data/misc/default.template +75 -0
- data/misc/htmldoc.metainfo +25 -0
- data/misc/htmldoc.virtual +5 -0
- data/misc/images/arrow.gif +0 -0
- data/misc/images/error.gif +0 -0
- data/misc/images/exclamation.gif +0 -0
- data/misc/images/headerbg.jpg +0 -0
- data/misc/images/information.gif +0 -0
- data/misc/images/quote.gif +0 -0
- data/setup.rb +1585 -0
- data/test/helper.rb +41 -0
- data/test/test_blackboard.rb +58 -0
- data/test/test_cache.rb +57 -0
- data/test/test_common_sitemap.rb +56 -0
- data/test/test_configuration.rb +66 -0
- data/test/test_contentprocessor.rb +31 -0
- data/test/test_contentprocessor_blocks.rb +34 -0
- data/test/test_contentprocessor_builder.rb +19 -0
- data/test/test_contentprocessor_context.rb +38 -0
- data/test/test_contentprocessor_erb.rb +20 -0
- data/test/test_contentprocessor_erubis.rb +47 -0
- data/test/test_contentprocessor_haml.rb +20 -0
- data/test/test_contentprocessor_maruku.rb +27 -0
- data/test/test_contentprocessor_rdiscount.rb +15 -0
- data/test/test_contentprocessor_rdoc.rb +16 -0
- data/test/test_contentprocessor_redcloth.rb +12 -0
- data/test/test_contentprocessor_sass.rb +20 -0
- data/test/test_contentprocessor_tags.rb +97 -0
- data/test/test_languages.rb +53 -0
- data/test/test_loggable.rb +30 -0
- data/test/test_logger.rb +73 -0
- data/test/test_node.rb +339 -0
- data/test/test_output_filesystem.rb +58 -0
- data/test/test_page.rb +203 -0
- data/test/test_path.rb +131 -0
- data/test/test_source_filesystem.rb +59 -0
- data/test/test_source_resource.rb +26 -0
- data/test/test_source_stacked.rb +34 -0
- data/test/test_sourcehandler_base.rb +92 -0
- data/test/test_sourcehandler_copy.rb +45 -0
- data/test/test_sourcehandler_directory.rb +25 -0
- data/test/test_sourcehandler_feed.rb +74 -0
- data/test/test_sourcehandler_fragment.rb +67 -0
- data/test/test_sourcehandler_metainfo.rb +93 -0
- data/test/test_sourcehandler_page.rb +70 -0
- data/test/test_sourcehandler_sitemap.rb +47 -0
- data/test/test_sourcehandler_template.rb +63 -0
- data/test/test_sourcehandler_virtual.rb +56 -0
- data/test/test_tag_base.rb +82 -0
- data/test/test_tag_breadcrumbtrail.rb +89 -0
- data/test/test_tag_coderay.rb +30 -0
- data/test/test_tag_date.rb +16 -0
- data/test/test_tag_executecommand.rb +39 -0
- data/test/test_tag_includefile.rb +48 -0
- data/test/test_tag_langbar.rb +60 -0
- data/test/test_tag_menu.rb +195 -0
- data/test/test_tag_metainfo.rb +17 -0
- data/test/test_tag_relocatable.rb +57 -0
- data/test/test_tag_sitemap.rb +44 -0
- data/test/test_tree.rb +69 -0
- data/test/test_webgentask.rb +21 -0
- data/test/test_website.rb +96 -0
- data/test/test_websiteaccess.rb +23 -0
- data/test/test_websitemanager.rb +68 -0
- metadata +575 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
module Webgen
|
2
|
+
|
3
|
+
# Namespace for all classes that know how to write out node content.
|
4
|
+
#
|
5
|
+
# = Implementing an output class
|
6
|
+
#
|
7
|
+
# Output classes know how to write rendered node data to an output location.
|
8
|
+
#
|
9
|
+
# An output class must respond to three methods
|
10
|
+
#
|
11
|
+
# <tt>exists?(path)</tt>::
|
12
|
+
# Return +true+ if the output path exists.
|
13
|
+
# <tt>delete(path)</tt>::
|
14
|
+
# Delete the given output path.
|
15
|
+
# <tt>write(path, data, type)</tt>::
|
16
|
+
# Write the data to the given output path. The parameter +type+ specifies the type of the
|
17
|
+
# to be written path: +:file+ or +:directory+.
|
18
|
+
# <tt>read(path)</tt>:
|
19
|
+
# Return the content of the given path if it exists or raise an error otherwise.
|
20
|
+
#
|
21
|
+
module Output
|
22
|
+
|
23
|
+
autoload :FileSystem, 'webgen/output/filesystem'
|
24
|
+
|
25
|
+
# Returns an instance of the configured output class.
|
26
|
+
def self.instance
|
27
|
+
classes = (WebsiteAccess.website.cache.volatile[:classes] ||= {})
|
28
|
+
unless classes.has_key?(:output_instance)
|
29
|
+
klass, *args = WebsiteAccess.website.config['output']
|
30
|
+
classes[:output_instance] = Object.constant(klass).new(*args)
|
31
|
+
end
|
32
|
+
classes[:output_instance]
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Webgen::Output
|
4
|
+
|
5
|
+
# This class uses the file systems as output device. On initialization a +root+ path is set and
|
6
|
+
# all other operations are taken relative to this root path.
|
7
|
+
class FileSystem
|
8
|
+
|
9
|
+
include Webgen::WebsiteAccess
|
10
|
+
|
11
|
+
# The root path, ie. the path to which the root node gets rendered.
|
12
|
+
attr_reader :root
|
13
|
+
|
14
|
+
# Create a new object with the given +root+ path. If +root+ is not absolute, it is taken
|
15
|
+
# relative to the website directory.
|
16
|
+
def initialize(root)
|
17
|
+
#TODO: copied from source/filesystem.rb
|
18
|
+
if root =~ /^([a-zA-Z]:|\/)/
|
19
|
+
@root = root
|
20
|
+
else
|
21
|
+
@root = File.join(website.directory, root)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return +true+ if the given path exists.
|
26
|
+
def exists?(path)
|
27
|
+
File.exists?(File.join(@root, path))
|
28
|
+
end
|
29
|
+
|
30
|
+
# Delete the given +path+
|
31
|
+
def delete(path)
|
32
|
+
dest = File.join(@root, path)
|
33
|
+
if File.directory?(dest)
|
34
|
+
FileUtils.rm_rf(dest)
|
35
|
+
else
|
36
|
+
FileUtils.rm(dest)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Write the +data+ to the given +path+. The +type+ parameter specifies the type of the path to
|
41
|
+
# be created which can either be <tt>:file</tt> or <tt>:directory</tt>.
|
42
|
+
def write(path, data, type = :file)
|
43
|
+
dest = File.join(@root, path)
|
44
|
+
FileUtils.makedirs(File.dirname(dest))
|
45
|
+
if type == :directory
|
46
|
+
FileUtils.makedirs(dest)
|
47
|
+
elsif type == :file
|
48
|
+
if data.kind_of?(String)
|
49
|
+
File.open(dest, 'wb') {|f| f.write(data) }
|
50
|
+
else
|
51
|
+
data.stream do |source|
|
52
|
+
File.open(dest, 'wb') {|f| FileUtils.copy_stream(source, f) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
else
|
56
|
+
raise "Unsupported path type '#{type}' for #{path}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Return the content of the given +path+.
|
61
|
+
def read(path)
|
62
|
+
File.open(File.join(@root, path), 'rb') {|f| f.read}
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
data/lib/webgen/page.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Webgen
|
4
|
+
|
5
|
+
# A single block within a Page object. The content of the block can be rendered using the #render method.
|
6
|
+
class Block
|
7
|
+
|
8
|
+
# The name of the block.
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
# The content of the block.
|
12
|
+
attr_reader :content
|
13
|
+
|
14
|
+
# The options set specifically for this block.
|
15
|
+
attr_reader :options
|
16
|
+
|
17
|
+
# Create a new block with the name +name+ and the given +content+ and +options+.
|
18
|
+
def initialize(name, content, options)
|
19
|
+
@name, @content, @options = name, content, options
|
20
|
+
end
|
21
|
+
|
22
|
+
# Render the block using the provided context object. Uses the content processors specified in
|
23
|
+
# the +pipeline+ key of the +options+ attribute to do the actual rendering.
|
24
|
+
#
|
25
|
+
# Returns the given context with the rendered content.
|
26
|
+
def render(context)
|
27
|
+
context[:content] = @content.dup
|
28
|
+
context[:block] = self
|
29
|
+
@options['pipeline'].to_s.split(/,/).each do |processor|
|
30
|
+
raise "No such content processor available: #{processor}" unless context[:processors].has_key?(processor)
|
31
|
+
context[:processors][processor].call(context)
|
32
|
+
end
|
33
|
+
context
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
# Raised during parsing of data in Webgen Page Format if the data is invalid.
|
40
|
+
class WebgenPageFormatError < RuntimeError; end
|
41
|
+
|
42
|
+
# A Page object wraps a meta information hash and an array of Block objects. It is normally
|
43
|
+
# generated from a file or string in Webgen Page Format using the provided class methods.
|
44
|
+
class Page
|
45
|
+
|
46
|
+
RE_META_INFO_START = /\A---\s*(?:\n|\r|\r\n)/m
|
47
|
+
RE_META_INFO = /\A---\s*(?:\n|\r|\r\n).*?(?:\n|\r|\r\n)(?=---.*?(?:\n|\r|\r\n)|\Z)/m
|
48
|
+
RE_BLOCKS_OPTIONS = /^--- *?(?: *((?:\w+:[^\s]* *)*))?$|^$/
|
49
|
+
RE_BLOCKS_START = /^--- .*?$|^--- *$/
|
50
|
+
RE_BLOCKS = /(?:(#{RE_BLOCKS_START})|\A)(.*?)(?:(?=#{RE_BLOCKS_START})|\Z)/m
|
51
|
+
|
52
|
+
class << self
|
53
|
+
|
54
|
+
# Parse the given string +data+ in Webgen Page Format and initialize a new Page object with
|
55
|
+
# the information. The +meta_info+ parameter can be used to provide default meta information.
|
56
|
+
def from_data(data, meta_info = {})
|
57
|
+
md = /(#{RE_META_INFO})?(.*)/m.match(normalize_eol(data))
|
58
|
+
if md[1].nil? && data =~ RE_META_INFO_START
|
59
|
+
raise WebgenPageFormatError, 'Found start line for meta information block but no valid meta information block'
|
60
|
+
end
|
61
|
+
meta_info = meta_info.merge(md[1].nil? ? {} : parse_meta_info(md[1]))
|
62
|
+
blocks = parse_blocks(md[2] || '', meta_info)
|
63
|
+
new(meta_info, blocks)
|
64
|
+
end
|
65
|
+
|
66
|
+
#######
|
67
|
+
private
|
68
|
+
#######
|
69
|
+
|
70
|
+
# Normalize the end-of-line encodings to Unix style.
|
71
|
+
def normalize_eol(data)
|
72
|
+
data.gsub(/\r\n?/, "\n")
|
73
|
+
end
|
74
|
+
|
75
|
+
# Parse the meta info string +data+ and return the hash with the meta information.
|
76
|
+
def parse_meta_info(data)
|
77
|
+
begin
|
78
|
+
meta_info = YAML::load(data)
|
79
|
+
unless meta_info.kind_of?(Hash)
|
80
|
+
raise WebgenPageFormatError, "Invalid structure of meta information block: expected YAML hash but found #{meta_info.class}"
|
81
|
+
end
|
82
|
+
rescue ArgumentError => e
|
83
|
+
raise WebgenPageFormatError, e.message
|
84
|
+
end
|
85
|
+
meta_info
|
86
|
+
end
|
87
|
+
|
88
|
+
# Parse all blocks in +data+ and return them. Meta information can be provided in +meta_info+
|
89
|
+
# which is used for setting the block names and options.
|
90
|
+
def parse_blocks(data, meta_info)
|
91
|
+
scanned = data.scan(RE_BLOCKS)
|
92
|
+
raise(WebgenPageFormatError, 'No content blocks specified') if scanned.length == 0
|
93
|
+
|
94
|
+
blocks = {}
|
95
|
+
scanned.each_with_index do |block_data, index|
|
96
|
+
options, content = *block_data
|
97
|
+
md = RE_BLOCKS_OPTIONS.match(options.to_s)
|
98
|
+
raise(WebgenPageFormatError, "Found invalid blocks starting line for block #{index+1}: #{options}") if content =~ /\A---/ || md.nil?
|
99
|
+
options = Hash[*md[1].to_s.scan(/(\w+):([^\s]*)/).map {|k,v| [k, YAML::load(v)]}.flatten]
|
100
|
+
options = (meta_info['blocks']['default'] || {} rescue {}).
|
101
|
+
merge((meta_info['blocks'][index+1] || {} rescue {})).
|
102
|
+
merge(options)
|
103
|
+
|
104
|
+
name = options.delete('name') || (index == 0 ? 'content' : 'block' + (index + 1).to_s)
|
105
|
+
raise(WebgenPageFormatError, "Previously used name '#{name}' also used for block #{index+1}") if blocks.has_key?(name)
|
106
|
+
content ||= ''
|
107
|
+
content.gsub!(/^(\\+)(---.*?)$/) {|m| "\\" * ($1.length / 2) + $2}
|
108
|
+
content.strip!
|
109
|
+
blocks[name] = blocks[index+1] = Block.new(name, content, options)
|
110
|
+
end
|
111
|
+
meta_info.delete('blocks')
|
112
|
+
blocks
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
# The contents of the meta information block.
|
119
|
+
attr_reader :meta_info
|
120
|
+
|
121
|
+
# The array of blocks for the page.
|
122
|
+
attr_reader :blocks
|
123
|
+
|
124
|
+
# Create a new Page object with the meta information provided in +meta_info+ and the given
|
125
|
+
# +blocks+.
|
126
|
+
def initialize(meta_info = {}, blocks = nil)
|
127
|
+
@meta_info = meta_info
|
128
|
+
@blocks = blocks
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
data/lib/webgen/path.rb
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'webgen/languages'
|
2
|
+
|
3
|
+
module Webgen
|
4
|
+
|
5
|
+
# A path object provides information about a specific path as well as methods for accessing its
|
6
|
+
# content.
|
7
|
+
#
|
8
|
+
# A webgen source class needs to derive a specialized path class from this class and implement an
|
9
|
+
# approriate #changed? method that returns +true+ if the path's content has changed since the last
|
10
|
+
# webgen run.
|
11
|
+
class Path
|
12
|
+
|
13
|
+
# Helper class for easy access to the content of a path.
|
14
|
+
class SourceIO
|
15
|
+
|
16
|
+
# Create a new SourceIO object. A block has to be specified that returns an IO object.
|
17
|
+
def initialize(&block)
|
18
|
+
@block = block
|
19
|
+
raise ArgumentError, 'Need to provide a block which returns an IO object' if @block.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
# Provide direct access to the wrapped IO object.
|
23
|
+
def stream
|
24
|
+
io = @block.call
|
25
|
+
yield(io)
|
26
|
+
ensure
|
27
|
+
io.close
|
28
|
+
end
|
29
|
+
|
30
|
+
# Return the content of the wrapped IO object as string.
|
31
|
+
def data
|
32
|
+
stream {|io| io.read}
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
include Comparable
|
39
|
+
|
40
|
+
# The full source path.
|
41
|
+
attr_accessor :path
|
42
|
+
|
43
|
+
# The basename part of the path.
|
44
|
+
attr_accessor :basename
|
45
|
+
|
46
|
+
# The directory part of the path.
|
47
|
+
attr_accessor :directory
|
48
|
+
|
49
|
+
# The canonical name without the extension.
|
50
|
+
attr_accessor :cnbase
|
51
|
+
|
52
|
+
# The extension.
|
53
|
+
attr_accessor :ext
|
54
|
+
|
55
|
+
# Extracted meta information for the path.
|
56
|
+
attr_accessor :meta_info
|
57
|
+
|
58
|
+
# Create a new Path object for +path+. The optional block needs to return an IO object for the
|
59
|
+
# content of the path.
|
60
|
+
def initialize(path, &ioblock)
|
61
|
+
@meta_info = {}
|
62
|
+
@io = SourceIO.new(&ioblock) if block_given?
|
63
|
+
analyse(path)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Mount this path at the mount point +mp+ optionally stripping +prefix+ from the path and return
|
67
|
+
# the new path object.
|
68
|
+
def mount_at(mp, prefix = nil)
|
69
|
+
temp = dup
|
70
|
+
temp.path = temp.path.sub(/^#{Regexp.escape(prefix.chomp("/"))}/, '') if prefix #"
|
71
|
+
reanalyse = (@path == '/' || temp.path == '/')
|
72
|
+
temp.path = File.join(mp, temp.path)
|
73
|
+
if reanalyse
|
74
|
+
temp.send(:analyse, temp.path)
|
75
|
+
else
|
76
|
+
temp.directory = File.join(File.dirname(temp.path), '/')
|
77
|
+
end
|
78
|
+
temp
|
79
|
+
end
|
80
|
+
|
81
|
+
# Has the content of this path changed since the last webgen run? This default implementation
|
82
|
+
# always returns +true+, a specialized sub class needs to override this behaviour!
|
83
|
+
def changed?
|
84
|
+
true
|
85
|
+
end
|
86
|
+
|
87
|
+
# Duplicate the path object.
|
88
|
+
def dup
|
89
|
+
temp = super
|
90
|
+
temp.meta_info = @meta_info.dup
|
91
|
+
temp
|
92
|
+
end
|
93
|
+
|
94
|
+
# The IO object associated with the path.
|
95
|
+
def io
|
96
|
+
if @io
|
97
|
+
@io
|
98
|
+
else
|
99
|
+
raise "No IO object defined for the path #{self}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# The canonical name created from the filename (created from cnbase and extension).
|
104
|
+
def cn
|
105
|
+
@cnbase + (@ext.length > 0 ? '.' + @ext : '')
|
106
|
+
end
|
107
|
+
|
108
|
+
# Utility method for creating the lcn from +cn+ and the language +lang+.
|
109
|
+
def self.lcn(cn, lang)
|
110
|
+
if lang.nil?
|
111
|
+
cn
|
112
|
+
else
|
113
|
+
cn.split('.').insert(1, lang.to_s).join('.')
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# The localized canonical name created from the filename.
|
118
|
+
def lcn
|
119
|
+
self.class.lcn(cn, @meta_info['lang'])
|
120
|
+
end
|
121
|
+
|
122
|
+
# Compare this object to another Path or a String.
|
123
|
+
def ==(other)
|
124
|
+
if other.kind_of?(Path)
|
125
|
+
other.path == @path
|
126
|
+
elsif other.kind_of?(String)
|
127
|
+
other == @path
|
128
|
+
else
|
129
|
+
false
|
130
|
+
end
|
131
|
+
end
|
132
|
+
alias_method(:eql?, :==)
|
133
|
+
|
134
|
+
# Return +true+ if the localized path matches the given +pattern+. For information on which
|
135
|
+
# patterns are supported, have a look at the documentation of File.fnmatch.
|
136
|
+
def =~(pattern)
|
137
|
+
File.fnmatch(pattern, File.join(@directory, lcn), File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Implemented sothat a Path looks like a String when used as key in a hash.
|
141
|
+
def <=>(other)
|
142
|
+
@path <=> other.to_str
|
143
|
+
end
|
144
|
+
|
145
|
+
# Implemented sothat a Path looks like a String when used as key in a hash.
|
146
|
+
def hash
|
147
|
+
@path.hash
|
148
|
+
end
|
149
|
+
|
150
|
+
def to_s #:nodoc:
|
151
|
+
@path.dup
|
152
|
+
end
|
153
|
+
alias_method :to_str, :to_s
|
154
|
+
|
155
|
+
def inspect #:nodoc:
|
156
|
+
"#<Path: #{@path}>"
|
157
|
+
end
|
158
|
+
|
159
|
+
#######
|
160
|
+
private
|
161
|
+
#######
|
162
|
+
|
163
|
+
FILENAME_RE = /^(?:(\d+)\.)?([^.]*?)(?:\.(\w\w\w?)(?=.))?(?:\.(.*))?$/
|
164
|
+
|
165
|
+
# Analyse the +path+ and fill the object with the extracted information.
|
166
|
+
def analyse(path)
|
167
|
+
@path = path
|
168
|
+
@basename = File.basename(path)
|
169
|
+
@directory = File.join(File.dirname(path), '/')
|
170
|
+
matchData = FILENAME_RE.match(@basename)
|
171
|
+
|
172
|
+
@meta_info['sort_info'] = (matchData[1].nil? ? nil : matchData[1].to_i)
|
173
|
+
@cnbase = matchData[2]
|
174
|
+
@meta_info['lang'] = Webgen::LanguageManager.language_for_code(matchData[3])
|
175
|
+
@ext = (@meta_info['lang'].nil? && !matchData[3].nil? ? matchData[3].to_s + '.' : '') + matchData[4].to_s
|
176
|
+
|
177
|
+
@meta_info['title'] = @cnbase.tr('_-', ' ').capitalize
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Webgen
|
2
|
+
|
3
|
+
# Namespace for all classes that provide source paths.
|
4
|
+
#
|
5
|
+
# = Implementing a source class
|
6
|
+
#
|
7
|
+
# Source classes provide access to the source paths on which the source handlers act.
|
8
|
+
#
|
9
|
+
# A source class only needs to respond to the method +paths+ which needs to return a set of paths
|
10
|
+
# for the source. The returned paths must respond to the method <tt>changed?</tt> (has to return
|
11
|
+
# +true+ if the paths has changed since the last webgen run) which is not implemented in the
|
12
|
+
# default Path class. One can either derive a specialized path class or define singleton methods
|
13
|
+
# on each path object.
|
14
|
+
#
|
15
|
+
module Source
|
16
|
+
|
17
|
+
autoload :Base, 'webgen/source/base'
|
18
|
+
autoload :FileSystem, 'webgen/source/filesystem'
|
19
|
+
autoload :Stacked, 'webgen/source/stacked'
|
20
|
+
autoload :Resource, 'webgen/source/resource'
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|