thewoolleyman-webgen 0.5.8.20090419
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 +8 -0
- data/COPYING +10 -0
- data/GPL +340 -0
- data/Rakefile +334 -0
- data/THANKS +18 -0
- data/bin/webgen +12 -0
- data/data/webgen/resources.yaml +3 -0
- data/data/webgen/webgui/controller/main.rb +135 -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 +10 -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 +62 -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 +129 -0
- data/doc/contentprocessor/builder.page +80 -0
- data/doc/contentprocessor/erb.page +59 -0
- data/doc/contentprocessor/erubis.page +46 -0
- data/doc/contentprocessor/fragments.page +25 -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 +219 -0
- data/doc/getting_started.page +135 -0
- data/doc/index.page +65 -0
- data/doc/manual.page +589 -0
- data/doc/reference_configuration.page +959 -0
- data/doc/reference_metainfo.page +222 -0
- data/doc/source/filesystem.page +39 -0
- data/doc/source/tararchive.page +40 -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 +105 -0
- data/doc/sourcehandler/metainfo.page +41 -0
- data/doc/sourcehandler/page.page +14 -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 +44 -0
- data/doc/tag/link.page +44 -0
- data/doc/tag/menu.page +106 -0
- data/doc/tag/metainfo.page +29 -0
- data/doc/tag/relocatable.page +38 -0
- data/doc/tag/sitemap.page +31 -0
- data/doc/tag/tikz.page +158 -0
- data/doc/upgrading.page +139 -0
- data/doc/webgen_page_format.page +129 -0
- data/lib/webgen/blackboard.rb +78 -0
- data/lib/webgen/cache.rb +87 -0
- data/lib/webgen/cli.rb +124 -0
- data/lib/webgen/cli/apply_command.rb +64 -0
- data/lib/webgen/cli/create_command.rb +66 -0
- data/lib/webgen/cli/run_command.rb +22 -0
- data/lib/webgen/cli/utils.rb +88 -0
- data/lib/webgen/cli/webgui_command.rb +72 -0
- data/lib/webgen/common.rb +21 -0
- data/lib/webgen/common/sitemap.rb +83 -0
- data/lib/webgen/configuration.rb +153 -0
- data/lib/webgen/contentprocessor.rb +99 -0
- data/lib/webgen/contentprocessor/blocks.rb +60 -0
- data/lib/webgen/contentprocessor/builder.rb +30 -0
- data/lib/webgen/contentprocessor/context.rb +89 -0
- data/lib/webgen/contentprocessor/erb.rb +28 -0
- data/lib/webgen/contentprocessor/erubis.rb +40 -0
- data/lib/webgen/contentprocessor/fragments.rb +25 -0
- data/lib/webgen/contentprocessor/haml.rb +30 -0
- data/lib/webgen/contentprocessor/maruku.rb +20 -0
- data/lib/webgen/contentprocessor/rdiscount.rb +17 -0
- data/lib/webgen/contentprocessor/rdoc.rb +19 -0
- data/lib/webgen/contentprocessor/redcloth.rb +17 -0
- data/lib/webgen/contentprocessor/sass.rb +20 -0
- data/lib/webgen/contentprocessor/tags.rb +136 -0
- data/lib/webgen/coreext.rb +13 -0
- data/lib/webgen/default_config.rb +215 -0
- data/lib/webgen/languages.rb +589 -0
- data/lib/webgen/loggable.rb +25 -0
- data/lib/webgen/logger.rb +97 -0
- data/lib/webgen/node.rb +391 -0
- data/lib/webgen/output.rb +82 -0
- data/lib/webgen/output/filesystem.rb +69 -0
- data/lib/webgen/page.rb +153 -0
- data/lib/webgen/path.rb +194 -0
- data/lib/webgen/source.rb +54 -0
- data/lib/webgen/source/filesystem.rb +61 -0
- data/lib/webgen/source/resource.rb +44 -0
- data/lib/webgen/source/stacked.rb +55 -0
- data/lib/webgen/source/tararchive.rb +73 -0
- data/lib/webgen/sourcehandler.rb +226 -0
- data/lib/webgen/sourcehandler/base.rb +248 -0
- data/lib/webgen/sourcehandler/copy.rb +43 -0
- data/lib/webgen/sourcehandler/directory.rb +36 -0
- data/lib/webgen/sourcehandler/feed.rb +117 -0
- data/lib/webgen/sourcehandler/fragment.rb +68 -0
- data/lib/webgen/sourcehandler/memory.rb +43 -0
- data/lib/webgen/sourcehandler/metainfo.rb +128 -0
- data/lib/webgen/sourcehandler/page.rb +59 -0
- data/lib/webgen/sourcehandler/sitemap.rb +60 -0
- data/lib/webgen/sourcehandler/template.rb +66 -0
- data/lib/webgen/sourcehandler/virtual.rb +110 -0
- data/lib/webgen/tag.rb +27 -0
- data/lib/webgen/tag/base.rb +170 -0
- data/lib/webgen/tag/breadcrumbtrail.rb +70 -0
- data/lib/webgen/tag/coderay.rb +31 -0
- data/lib/webgen/tag/date.rb +18 -0
- data/lib/webgen/tag/executecommand.rb +30 -0
- data/lib/webgen/tag/includefile.rb +42 -0
- data/lib/webgen/tag/langbar.rb +52 -0
- data/lib/webgen/tag/link.rb +26 -0
- data/lib/webgen/tag/menu.rb +207 -0
- data/lib/webgen/tag/metainfo.rb +25 -0
- data/lib/webgen/tag/relocatable.rb +54 -0
- data/lib/webgen/tag/sitemap.rb +41 -0
- data/lib/webgen/tag/tikz.rb +119 -0
- data/lib/webgen/tree.rb +90 -0
- data/lib/webgen/version.rb +8 -0
- data/lib/webgen/webgentask.rb +152 -0
- data/lib/webgen/website.rb +342 -0
- data/lib/webgen/websiteaccess.rb +31 -0
- data/lib/webgen/websitemanager.rb +127 -0
- data/man/man1/webgen.1 +73 -0
- data/misc/default.css +384 -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.png +0 -0
- data/misc/images/headerbg.jpg +0 -0
- data/misc/images/important.png +0 -0
- data/misc/images/information.png +0 -0
- data/misc/images/quote.gif +0 -0
- data/misc/images/warning.png +0 -0
- data/setup.rb +1585 -0
- data/test/helper.rb +45 -0
- data/test/test_blackboard.rb +60 -0
- data/test/test_cache.rb +59 -0
- data/test/test_cli.rb +21 -0
- data/test/test_common.rb +18 -0
- data/test/test_common_sitemap.rb +58 -0
- data/test/test_configuration.rb +68 -0
- data/test/test_contentprocessor.rb +33 -0
- data/test/test_contentprocessor_blocks.rb +68 -0
- data/test/test_contentprocessor_builder.rb +23 -0
- data/test/test_contentprocessor_context.rb +40 -0
- data/test/test_contentprocessor_erb.rb +23 -0
- data/test/test_contentprocessor_erubis.rb +49 -0
- data/test/test_contentprocessor_fragments.rb +42 -0
- data/test/test_contentprocessor_haml.rb +23 -0
- data/test/test_contentprocessor_maruku.rb +29 -0
- data/test/test_contentprocessor_rdiscount.rb +17 -0
- data/test/test_contentprocessor_rdoc.rb +18 -0
- data/test/test_contentprocessor_redcloth.rb +15 -0
- data/test/test_contentprocessor_sass.rb +22 -0
- data/test/test_contentprocessor_tags.rb +99 -0
- data/test/test_languages.rb +67 -0
- data/test/test_loggable.rb +32 -0
- data/test/test_logger.rb +94 -0
- data/test/test_node.rb +367 -0
- data/test/test_output_filesystem.rb +60 -0
- data/test/test_page.rb +214 -0
- data/test/test_path.rb +165 -0
- data/test/test_source_filesystem.rb +76 -0
- data/test/test_source_resource.rb +28 -0
- data/test/test_source_stacked.rb +36 -0
- data/test/test_source_tararchive.rb +65 -0
- data/test/test_sourcehandler_base.rb +123 -0
- data/test/test_sourcehandler_copy.rb +47 -0
- data/test/test_sourcehandler_directory.rb +42 -0
- data/test/test_sourcehandler_feed.rb +77 -0
- data/test/test_sourcehandler_fragment.rb +69 -0
- data/test/test_sourcehandler_memory.rb +44 -0
- data/test/test_sourcehandler_metainfo.rb +118 -0
- data/test/test_sourcehandler_page.rb +65 -0
- data/test/test_sourcehandler_sitemap.rb +49 -0
- data/test/test_sourcehandler_template.rb +65 -0
- data/test/test_sourcehandler_virtual.rb +87 -0
- data/test/test_tag_base.rb +85 -0
- data/test/test_tag_breadcrumbtrail.rb +91 -0
- data/test/test_tag_coderay.rb +32 -0
- data/test/test_tag_date.rb +18 -0
- data/test/test_tag_executecommand.rb +41 -0
- data/test/test_tag_includefile.rb +50 -0
- data/test/test_tag_langbar.rb +72 -0
- data/test/test_tag_link.rb +69 -0
- data/test/test_tag_menu.rb +207 -0
- data/test/test_tag_metainfo.rb +19 -0
- data/test/test_tag_relocatable.rb +59 -0
- data/test/test_tag_sitemap.rb +47 -0
- data/test/test_tag_tikz.rb +69 -0
- data/test/test_tree.rb +70 -0
- data/test/test_webgentask.rb +23 -0
- data/test/test_website.rb +98 -0
- data/test/test_websiteaccess.rb +25 -0
- data/test/test_websitemanager.rb +70 -0
- metadata +613 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Webgen
|
4
|
+
|
5
|
+
# Namespace for all classes that know how to write out node content.
|
6
|
+
#
|
7
|
+
# == Implementing an output class
|
8
|
+
#
|
9
|
+
# Output classes know how to write rendered node data to an output location.
|
10
|
+
#
|
11
|
+
# An output class must respond to three methods
|
12
|
+
#
|
13
|
+
# [<tt>exists?(path)</tt>]
|
14
|
+
# Return +true+ if the output path exists.
|
15
|
+
# [<tt>delete(path)</tt>]
|
16
|
+
# Delete the given output path.
|
17
|
+
# [<tt>write(path, data, type)</tt>]
|
18
|
+
# Write the +data+ to the given output +path+. The parameter +data+ is either a String with the
|
19
|
+
# content or a Webgen::Path::SourceIO object. The parameter +type+ specifies the type of the to
|
20
|
+
# be written path: <tt>:file</tt> or <tt>:directory</tt>.
|
21
|
+
# [<tt>read(path)</tt>]
|
22
|
+
# Return the content of the given path if it exists or raise an error otherwise.
|
23
|
+
#
|
24
|
+
# It seems a bit odd that an output instance has to implement reading functionality. However,
|
25
|
+
# consider the case where you want webgen to render a website programmatically and *use* the
|
26
|
+
# output. In this case you need a way to get to content of the written files! This functionality
|
27
|
+
# is used, for example, in the webgui.
|
28
|
+
#
|
29
|
+
# == Sample Output Class
|
30
|
+
#
|
31
|
+
# Following is a simple but actually used (by the webgui) output class which stores the written
|
32
|
+
# nodes in a hash in memory:
|
33
|
+
#
|
34
|
+
# class MemoryOutput
|
35
|
+
# include Webgen::WebsiteAccess
|
36
|
+
#
|
37
|
+
# attr_reader :data
|
38
|
+
#
|
39
|
+
# def initialize
|
40
|
+
# @data = {}
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# def exists?(path)
|
44
|
+
# @data.has_key?(path)
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# def delete(path)
|
48
|
+
# @data.delete(path)
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# def write(path, io, type = :file)
|
52
|
+
# @data[path] = [(io.kind_of?(String) ? io : io.data), type]
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# def read(path)
|
56
|
+
# path = File.join('/', path)
|
57
|
+
# raise "No such file #{path}" unless @data[path] && @data[path].last == :file
|
58
|
+
# @data[path].first
|
59
|
+
# end
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# WebsiteAccess.website.config.output(['MemoryOutput'])
|
63
|
+
#
|
64
|
+
# The last line is used to tell webgen to use this new output class instead of the default one.
|
65
|
+
#
|
66
|
+
module Output
|
67
|
+
|
68
|
+
autoload :FileSystem, 'webgen/output/filesystem'
|
69
|
+
|
70
|
+
# Returns an instance of the configured output class.
|
71
|
+
def self.instance
|
72
|
+
classes = (WebsiteAccess.website.cache.volatile[:classes] ||= {})
|
73
|
+
unless classes.has_key?(:output_instance)
|
74
|
+
klass, *args = WebsiteAccess.website.config['output']
|
75
|
+
classes[:output_instance] = Object.constant(klass).new(*args)
|
76
|
+
end
|
77
|
+
classes[:output_instance]
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Webgen::Output
|
6
|
+
|
7
|
+
# This class uses the file systems as output device. On initialization a +root+ path is set and
|
8
|
+
# all other operations are taken relative to this root path.
|
9
|
+
class FileSystem
|
10
|
+
|
11
|
+
include Webgen::WebsiteAccess
|
12
|
+
|
13
|
+
# The root path, ie. the path to which the root node gets rendered.
|
14
|
+
attr_reader :root
|
15
|
+
|
16
|
+
# Create a new object with the given +root+ path. If +root+ is not absolute, it is taken
|
17
|
+
# relative to the website directory.
|
18
|
+
def initialize(root)
|
19
|
+
#TODO: copied from source/filesystem.rb
|
20
|
+
if root =~ /^([a-zA-Z]:|\/)/
|
21
|
+
@root = root
|
22
|
+
else
|
23
|
+
@root = File.join(website.directory, root)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Return +true+ if the given path exists.
|
28
|
+
def exists?(path)
|
29
|
+
File.exists?(File.join(@root, path))
|
30
|
+
end
|
31
|
+
|
32
|
+
# Delete the given +path+
|
33
|
+
def delete(path)
|
34
|
+
dest = File.join(@root, path)
|
35
|
+
if File.directory?(dest)
|
36
|
+
FileUtils.rm_rf(dest)
|
37
|
+
else
|
38
|
+
FileUtils.rm(dest)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Write the +data+ to the given +path+. The +type+ parameter specifies the type of the path to
|
43
|
+
# be created which can either be <tt>:file</tt> or <tt>:directory</tt>.
|
44
|
+
def write(path, data, type = :file)
|
45
|
+
dest = File.join(@root, path)
|
46
|
+
FileUtils.makedirs(File.dirname(dest))
|
47
|
+
if type == :directory
|
48
|
+
FileUtils.makedirs(dest)
|
49
|
+
elsif type == :file
|
50
|
+
if data.kind_of?(String)
|
51
|
+
File.open(dest, 'wb') {|f| f.write(data) }
|
52
|
+
else
|
53
|
+
data.stream do |source|
|
54
|
+
File.open(dest, 'wb') {|f| FileUtils.copy_stream(source, f) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
else
|
58
|
+
raise "Unsupported path type '#{type}' for #{path}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Return the content of the given +path+.
|
63
|
+
def read(path)
|
64
|
+
File.open(File.join(@root, path), 'rb') {|f| f.read}
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/lib/webgen/page.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Webgen
|
6
|
+
|
7
|
+
# A single block within a Page object. The content of the block can be rendered using the #render method.
|
8
|
+
class Block
|
9
|
+
|
10
|
+
# The name of the block.
|
11
|
+
attr_reader :name
|
12
|
+
|
13
|
+
# The content of the block.
|
14
|
+
attr_reader :content
|
15
|
+
|
16
|
+
# The options set specifically for this block.
|
17
|
+
attr_reader :options
|
18
|
+
|
19
|
+
# Create a new block with the name +name+ and the given +content+ and +options+.
|
20
|
+
def initialize(name, content, options)
|
21
|
+
@name, @content, @options = name, content, options
|
22
|
+
end
|
23
|
+
|
24
|
+
# Render the block using the provided context object.
|
25
|
+
#
|
26
|
+
# The context object needs to respond to <tt>#[]</tt> and <tt>#[]=</tt> (e.g. a Hash is a valid
|
27
|
+
# context object) and the key <tt>:processors</tt> needs to contain a Hash which maps processor
|
28
|
+
# names to processor objects that respond to <tt>#call</tt>.
|
29
|
+
#
|
30
|
+
# Uses the content processors specified in the +pipeline+ key of the +options+ attribute to do
|
31
|
+
# the actual rendering.
|
32
|
+
#
|
33
|
+
# Returns the given context with the rendered content.
|
34
|
+
def render(context)
|
35
|
+
context[:content] = @content.dup
|
36
|
+
context[:block] = self
|
37
|
+
@options['pipeline'].to_s.split(/,/).each do |processor|
|
38
|
+
raise "No such content processor available: #{processor}" unless context[:processors].has_key?(processor)
|
39
|
+
context[:processors][processor].call(context)
|
40
|
+
end
|
41
|
+
context
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# Raised during parsing of data in Webgen Page Format if the data is invalid.
|
48
|
+
class WebgenPageFormatError < RuntimeError; end
|
49
|
+
|
50
|
+
# A Page object wraps a meta information hash and an array of Block objects. It is normally
|
51
|
+
# generated from a file or string in Webgen Page Format using the provided class methods.
|
52
|
+
class Page
|
53
|
+
|
54
|
+
# :stopdoc:
|
55
|
+
RE_META_INFO_START = /\A---\s*(?:\n|\r|\r\n)/m
|
56
|
+
RE_META_INFO = /\A---\s*(?:\n|\r|\r\n).*?(?:\n|\r|\r\n)(?=---.*?(?:\n|\r|\r\n)|\Z)/m
|
57
|
+
RE_BLOCKS_OPTIONS = /^--- *?(?: *((?:\w+:[^\s]* *)*))?$|^$/
|
58
|
+
RE_BLOCKS_START = /^--- .*?$|^--- *$/
|
59
|
+
RE_BLOCKS = /(?:(#{RE_BLOCKS_START})|\A)(.*?)(?:(?=#{RE_BLOCKS_START})|\Z)/m
|
60
|
+
# :startdoc:
|
61
|
+
|
62
|
+
class << self
|
63
|
+
|
64
|
+
# Parse the given string +data+ in Webgen Page Format and initialize a new Page object with
|
65
|
+
# the information. The +meta_info+ parameter can be used to provide default meta information.
|
66
|
+
def from_data(data, meta_info = {})
|
67
|
+
md = /(#{RE_META_INFO})?(.*)/m.match(normalize_eol(data))
|
68
|
+
meta_info = meta_info.merge(parse_meta_info(md[1], data))
|
69
|
+
blocks = parse_blocks(md[2] || '', meta_info)
|
70
|
+
new(meta_info, blocks)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Parse the given string +data+ in Webgen Page Format and return the found meta information.
|
74
|
+
def meta_info_from_data(data)
|
75
|
+
md = /(#{RE_META_INFO})?/m.match(normalize_eol(data))
|
76
|
+
parse_meta_info(md[1], data)
|
77
|
+
end
|
78
|
+
|
79
|
+
#######
|
80
|
+
private
|
81
|
+
#######
|
82
|
+
|
83
|
+
# Normalize the end-of-line encodings to Unix style.
|
84
|
+
def normalize_eol(data)
|
85
|
+
data.gsub(/\r\n?/, "\n")
|
86
|
+
end
|
87
|
+
|
88
|
+
# Parse the meta info string in +mi_data+ and return the hash with the meta information. The
|
89
|
+
# original +data+ is used for checking the validness of the meta information block.
|
90
|
+
def parse_meta_info(mi_data, data)
|
91
|
+
if mi_data.nil? && data =~ RE_META_INFO_START
|
92
|
+
raise WebgenPageFormatError, 'Found start line for meta information block but no valid meta information block'
|
93
|
+
elsif mi_data.nil?
|
94
|
+
{}
|
95
|
+
else
|
96
|
+
begin
|
97
|
+
meta_info = YAML::load(mi_data.to_s)
|
98
|
+
unless meta_info.kind_of?(Hash)
|
99
|
+
raise WebgenPageFormatError, "Invalid structure of meta information block: expected YAML hash but found #{meta_info.class}"
|
100
|
+
end
|
101
|
+
rescue ArgumentError => e
|
102
|
+
raise WebgenPageFormatError, e.message
|
103
|
+
end
|
104
|
+
meta_info
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Parse all blocks in +data+ and return them. Meta information can be provided in +meta_info+
|
109
|
+
# which is used for setting the block names and options.
|
110
|
+
def parse_blocks(data, meta_info)
|
111
|
+
scanned = data.scan(RE_BLOCKS)
|
112
|
+
raise(WebgenPageFormatError, 'No content blocks specified') if scanned.length == 0
|
113
|
+
|
114
|
+
blocks = {}
|
115
|
+
scanned.each_with_index do |block_data, index|
|
116
|
+
options, content = *block_data
|
117
|
+
md = RE_BLOCKS_OPTIONS.match(options.to_s)
|
118
|
+
raise(WebgenPageFormatError, "Found invalid blocks starting line for block #{index+1}: #{options}") if content =~ /\A---/ || md.nil?
|
119
|
+
options = Hash[*md[1].to_s.scan(/(\w+):([^\s]*)/).map {|k,v| [k, (v == '' ? nil : YAML::load(v))]}.flatten]
|
120
|
+
options = (meta_info['blocks']['default'] || {} rescue {}).
|
121
|
+
merge((meta_info['blocks'][index+1] || {} rescue {})).
|
122
|
+
merge(options)
|
123
|
+
|
124
|
+
name = options.delete('name') || (index == 0 ? 'content' : 'block' + (index + 1).to_s)
|
125
|
+
raise(WebgenPageFormatError, "Previously used name '#{name}' also used for block #{index+1}") if blocks.has_key?(name)
|
126
|
+
content ||= ''
|
127
|
+
content.gsub!(/^(\\+)(---.*?)$/) {|m| "\\" * ($1.length / 2) + $2}
|
128
|
+
content.strip!
|
129
|
+
blocks[name] = blocks[index+1] = Block.new(name, content, options)
|
130
|
+
end
|
131
|
+
meta_info.delete('blocks')
|
132
|
+
blocks
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
# The contents of the meta information block.
|
139
|
+
attr_reader :meta_info
|
140
|
+
|
141
|
+
# The hash of blocks for the page.
|
142
|
+
attr_reader :blocks
|
143
|
+
|
144
|
+
# Create a new Page object with the meta information provided in +meta_info+ and the given
|
145
|
+
# +blocks+.
|
146
|
+
def initialize(meta_info = {}, blocks = {})
|
147
|
+
@meta_info = meta_info
|
148
|
+
@blocks = blocks
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
data/lib/webgen/path.rb
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'webgen/languages'
|
4
|
+
|
5
|
+
module Webgen
|
6
|
+
|
7
|
+
# A path object provides information about a specific path as well as methods for accessing its
|
8
|
+
# content.
|
9
|
+
#
|
10
|
+
# A webgen source class needs to derive a specialized path class from this class and implement an
|
11
|
+
# approriate #changed? method that returns +true+ if the path's content has changed since the last
|
12
|
+
# webgen run.
|
13
|
+
class Path
|
14
|
+
|
15
|
+
# Helper class for easy access to the content of a path.
|
16
|
+
class SourceIO
|
17
|
+
|
18
|
+
# Create a new SourceIO object. A block has to be specified that returns an IO object.
|
19
|
+
def initialize(&block)
|
20
|
+
@block = block
|
21
|
+
raise ArgumentError, 'Need to provide a block which returns an IO object' if @block.nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
# Provide direct access to the wrapped IO object.
|
25
|
+
def stream
|
26
|
+
io = @block.call
|
27
|
+
yield(io)
|
28
|
+
ensure
|
29
|
+
io.close
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return the content of the wrapped IO object as string.
|
33
|
+
def data
|
34
|
+
stream {|io| io.read}
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
# Return +true+ if the given +path+ matches the given +pattern+ (trailing slashes of directories
|
41
|
+
# are not respected). For information on which patterns are supported, have a look at the
|
42
|
+
# documentation of File.fnmatch.
|
43
|
+
def self.match(path, pattern)
|
44
|
+
path = path.to_s.chomp('/') unless path == '/'
|
45
|
+
pattern = pattern.to_s.chomp('/') unless pattern == '/'
|
46
|
+
File.fnmatch(pattern, path, File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
include Comparable
|
51
|
+
|
52
|
+
# The full path.
|
53
|
+
attr_accessor :path
|
54
|
+
|
55
|
+
# The source path that lead to the creation of this path.
|
56
|
+
attr_accessor :source_path
|
57
|
+
|
58
|
+
# The basename part of the path.
|
59
|
+
attr_accessor :basename
|
60
|
+
|
61
|
+
# The directory part of the path.
|
62
|
+
attr_accessor :directory
|
63
|
+
|
64
|
+
# The canonical name without the extension.
|
65
|
+
attr_accessor :cnbase
|
66
|
+
|
67
|
+
# The extension.
|
68
|
+
attr_accessor :ext
|
69
|
+
|
70
|
+
# Extracted meta information for the path.
|
71
|
+
attr_accessor :meta_info
|
72
|
+
|
73
|
+
# Create a new Path object for +path+. The optional +source_path+ parameter specifies the path
|
74
|
+
# that lead to the creation of this path. The optional block needs to return an IO object for
|
75
|
+
# the content of the path.
|
76
|
+
def initialize(path, source_path = path, &ioblock)
|
77
|
+
@meta_info = {}
|
78
|
+
@io = block_given? ? SourceIO.new(&ioblock) : nil
|
79
|
+
@source_path = source_path
|
80
|
+
analyse(path)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Mount this path at the mount point +mp+ optionally stripping +prefix+ from the path and return
|
84
|
+
# the new path object.
|
85
|
+
def mount_at(mp, prefix = nil)
|
86
|
+
temp = dup
|
87
|
+
temp.path = temp.path.sub(/^#{Regexp.escape(prefix.chomp("/"))}/, '') if prefix #"
|
88
|
+
reanalyse = (@path == '/' || temp.path == '/')
|
89
|
+
temp.path = File.join(mp, temp.path)
|
90
|
+
temp.source_path = temp.path if @path == @source_path
|
91
|
+
if reanalyse
|
92
|
+
temp.send(:analyse, temp.path)
|
93
|
+
else
|
94
|
+
temp.directory = File.join(File.dirname(temp.path), '/')
|
95
|
+
end
|
96
|
+
temp
|
97
|
+
end
|
98
|
+
|
99
|
+
# Has the content of this path changed since the last webgen run? This default implementation
|
100
|
+
# always returns +true+, a specialized sub class needs to override this behaviour!
|
101
|
+
def changed?
|
102
|
+
true
|
103
|
+
end
|
104
|
+
|
105
|
+
# Duplicate the path object.
|
106
|
+
def dup
|
107
|
+
temp = super
|
108
|
+
temp.meta_info = @meta_info.dup
|
109
|
+
temp
|
110
|
+
end
|
111
|
+
|
112
|
+
# The SourceIO object associated with the path.
|
113
|
+
def io
|
114
|
+
if @io
|
115
|
+
@io
|
116
|
+
else
|
117
|
+
raise "No IO object defined for the path #{self}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# The canonical name created from the filename (created from cnbase and extension).
|
122
|
+
def cn
|
123
|
+
@cnbase + (@ext.length > 0 ? '.' + @ext : '')
|
124
|
+
end
|
125
|
+
|
126
|
+
# Utility method for creating the lcn from +cn+ and the language +lang+.
|
127
|
+
def self.lcn(cn, lang)
|
128
|
+
if lang.nil?
|
129
|
+
cn
|
130
|
+
else
|
131
|
+
cn.split('.').insert(1, lang.to_s).join('.')
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# The localized canonical name created from the filename.
|
136
|
+
def lcn
|
137
|
+
self.class.lcn(cn, @meta_info['lang'])
|
138
|
+
end
|
139
|
+
|
140
|
+
# Compare this object to another Path or a String.
|
141
|
+
def ==(other)
|
142
|
+
if other.kind_of?(Path)
|
143
|
+
other.path == @path
|
144
|
+
elsif other.kind_of?(String)
|
145
|
+
other == @path
|
146
|
+
else
|
147
|
+
false
|
148
|
+
end
|
149
|
+
end
|
150
|
+
alias_method(:eql?, :==)
|
151
|
+
|
152
|
+
# Implemented sothat a Path looks like a String when used as key in a hash.
|
153
|
+
def <=>(other)
|
154
|
+
@path <=> other.to_str
|
155
|
+
end
|
156
|
+
|
157
|
+
# Implemented sothat a Path looks like a String when used as key in a hash.
|
158
|
+
def hash
|
159
|
+
@path.hash
|
160
|
+
end
|
161
|
+
|
162
|
+
def to_s #:nodoc:
|
163
|
+
@path.dup
|
164
|
+
end
|
165
|
+
alias_method :to_str, :to_s
|
166
|
+
|
167
|
+
def inspect #:nodoc:
|
168
|
+
"#<Path: #{@path}>"
|
169
|
+
end
|
170
|
+
|
171
|
+
#######
|
172
|
+
private
|
173
|
+
#######
|
174
|
+
|
175
|
+
FILENAME_RE = /^(?:(\d+)\.)?([^.]*?)(?:\.(\w\w\w?)(?=.))?(?:\.(.*))?$/
|
176
|
+
|
177
|
+
# Analyse the +path+ and fill the object with the extracted information.
|
178
|
+
def analyse(path)
|
179
|
+
@path = path
|
180
|
+
@basename = File.basename(path)
|
181
|
+
@directory = File.join(File.dirname(path), '/')
|
182
|
+
matchData = FILENAME_RE.match(@basename)
|
183
|
+
|
184
|
+
@meta_info['sort_info'] = (matchData[1].nil? ? nil : matchData[1].to_i)
|
185
|
+
@cnbase = matchData[2]
|
186
|
+
@meta_info['lang'] = Webgen::LanguageManager.language_for_code(matchData[3])
|
187
|
+
@ext = (@meta_info['lang'].nil? && !matchData[3].nil? ? matchData[3].to_s + '.' : '') + matchData[4].to_s
|
188
|
+
|
189
|
+
@meta_info['title'] = @cnbase.tr('_-', ' ').capitalize
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|