thewoolleyman-webgen 0.5.8.20090419
Sign up to get free protection for your applications and to get access to all the features.
- 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,248 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'facets/symbol/to_proc'
|
4
|
+
require 'webgen/websiteaccess'
|
5
|
+
require 'webgen/loggable'
|
6
|
+
require 'webgen/page'
|
7
|
+
|
8
|
+
module Webgen::SourceHandler
|
9
|
+
|
10
|
+
# This module should be included in every source handler as it provides the default methods for
|
11
|
+
# creating nodes.
|
12
|
+
#
|
13
|
+
# == Implementing Source Handlers
|
14
|
+
#
|
15
|
+
# A source handler is a webgen extension that processes source paths to create nodes and that
|
16
|
+
# provides the rendered content of these nodes. The nodes are later written to the output
|
17
|
+
# location. This can range from simply copying a path from the source to the output location to
|
18
|
+
# generating a whole set of nodes from one input path!
|
19
|
+
#
|
20
|
+
# The paths that are handled by a source handler are specified via path patterns (see
|
21
|
+
# below). During a webgen run the #create_node method for each source paths that matches a
|
22
|
+
# specified path pattern is called. And when it is time to write out the node, the the #content
|
23
|
+
# method is called to retrieve the rendered content.
|
24
|
+
#
|
25
|
+
# A source handler must not take any parameters on initialization and when this module is not
|
26
|
+
# mixed in, the methods #create_node and #content need to be defined. Also, a source handler does
|
27
|
+
# not need to reside under the Webgen::SourceHandler namespace but all shipped ones do.
|
28
|
+
#
|
29
|
+
# This base class provides useful default implementations of methods that are used by nearly all
|
30
|
+
# source handler classes:
|
31
|
+
# * #create_node
|
32
|
+
# * #output_path
|
33
|
+
# * #node_exists?
|
34
|
+
#
|
35
|
+
# It also provides other utility methods:
|
36
|
+
# * #page_from_path
|
37
|
+
# * #content
|
38
|
+
#
|
39
|
+
# == Nodes Created for Paths
|
40
|
+
#
|
41
|
+
# The main functions of a source handler class are to create one or more nodes for a source path
|
42
|
+
# and to provide the content of these nodes. To achieve this, certain information needs to be set
|
43
|
+
# on a created node. If you use the +create_node+ method provided by this base class, you don't
|
44
|
+
# need to set them explicitly because this is done by the method:
|
45
|
+
#
|
46
|
+
# [<tt>node_info[:processor]</tt>] Has to be set to the class name of the source handler. This is
|
47
|
+
# used by the Node class: all unknown method calls are forwarded
|
48
|
+
# to the node processor.
|
49
|
+
# [<tt>node_info[:src]</tt>] Has to be set to the string version of the path that lead to the
|
50
|
+
# creation of the node.
|
51
|
+
# [<tt>node_info[:creation_path]</tt>] Has to be set to the string version of the path that is
|
52
|
+
# used to create the path.
|
53
|
+
# [<tt>meta_info['no_output']</tt>] Has to be set to +true+ on nodes that are used during a
|
54
|
+
# webgen run but do not produce an output file.
|
55
|
+
# [<tt>meta_info['modified_at']</tt>] Has to be set to the current time if not already set
|
56
|
+
# correctly (ie. if not a Time object).
|
57
|
+
#
|
58
|
+
# If <tt>meta_info['draft']</tt> is set on a path, then no node should be created in +create_node+
|
59
|
+
# and +nil+ has to be returned.
|
60
|
+
#
|
61
|
+
# Note: The difference between +:src+ and +:creation_path+ is that a creation path
|
62
|
+
# need not have an existing source path representation. For example, fragments created from a page
|
63
|
+
# source path have a different +:creation_path+ which includes the fragment part.
|
64
|
+
#
|
65
|
+
# Additional information that is used only for processing purposes should be stored in the
|
66
|
+
# #node_info hash of a node as the #meta_info hash is reserved for real node meta information and
|
67
|
+
# should not be changed once the node is created.
|
68
|
+
#
|
69
|
+
# == Output Path Names
|
70
|
+
#
|
71
|
+
# The method for creating an output path name for a source path is stored in the meta information
|
72
|
+
# +output_path+. If you don't use the provided method +output_path+, have a look at its
|
73
|
+
# implementation to see how to an output path gets created. Individual output path creation
|
74
|
+
# methods are stored as methods in the OutputPathHelpers module.
|
75
|
+
#
|
76
|
+
# == Path Patterns and Invocation order
|
77
|
+
#
|
78
|
+
# Path patterns define which paths are handled by a specific source handler. These patterns are
|
79
|
+
# specified in the <tt>sourcehandler.patterns</tt> configuration hash as a mapping from the source
|
80
|
+
# handler class name to an array of path patterns. The patterns need to have a format that
|
81
|
+
# <tt>Dir.glob</tt> can handle. You can use the configuration helper +patterns+ to set this (is
|
82
|
+
# shown in the example below).
|
83
|
+
#
|
84
|
+
# Specifying a path pattern does not mean that webgen uses the source handler. One also needs to
|
85
|
+
# provide an entry in the configuration value <tt>sourcehandler.invoke</tt>. This is a hash that
|
86
|
+
# maps the invocation rank (a number) to an array of source handler class names. The lower the
|
87
|
+
# invocation rank the earlier the specified source handlers are used.
|
88
|
+
#
|
89
|
+
# The default invocation ranks are:
|
90
|
+
# [1] Early. Normally there is no need to use this rank.
|
91
|
+
# [5] Standard. This is the rank the normal source handler should use.
|
92
|
+
# [9] Late. This rank should be used by source handlers that operate on/use already created nodes
|
93
|
+
# and need to ensure that these nodes are available.
|
94
|
+
#
|
95
|
+
# == Default Meta Information
|
96
|
+
#
|
97
|
+
# Each source handler can define default meta information that gets automatically set on the
|
98
|
+
# source paths that are passed to the #create_node method.
|
99
|
+
#
|
100
|
+
# The default meta information is specified in the <tt>sourcehandler.default_meta_info</tt>
|
101
|
+
# configuration hash as a mapping from the source handler class name to the meta information
|
102
|
+
# hash.
|
103
|
+
#
|
104
|
+
# == Sample Source Handler Class
|
105
|
+
#
|
106
|
+
# Following is a simple source handler class example which copies paths from the source to
|
107
|
+
# the output location modifying the extension:
|
108
|
+
#
|
109
|
+
# class SimpleCopy
|
110
|
+
#
|
111
|
+
# include Webgen::SourceHandler::Base
|
112
|
+
#
|
113
|
+
# def create_node(parent, path)
|
114
|
+
# path.ext += '.copied'
|
115
|
+
# super(parent, path)
|
116
|
+
# end
|
117
|
+
#
|
118
|
+
# def content(node)
|
119
|
+
# website.blackboard.invoke(:source_paths)[node.node_info[:src]].io
|
120
|
+
# end
|
121
|
+
#
|
122
|
+
# end
|
123
|
+
#
|
124
|
+
# WebsiteAccess.website.config.patterns('SimpleCopy' => ['**/*.jpg', '**/*.png'])
|
125
|
+
# WebsiteAccess.website.config.sourcehandler.invoke[5] << 'SimpleCopy'
|
126
|
+
#
|
127
|
+
module Base
|
128
|
+
|
129
|
+
# This module is used for defining all methods that can be used for creating output paths.
|
130
|
+
#
|
131
|
+
# All public methods of this module are considered to be output path creation methods and must
|
132
|
+
# have the following parameters:
|
133
|
+
#
|
134
|
+
# [+parent+] the parent node
|
135
|
+
# [+path+] the path for which the output name should be created
|
136
|
+
# [+use_lang_part+] controls whether the output path name has to include the language part
|
137
|
+
module OutputPathHelpers
|
138
|
+
|
139
|
+
# Default method for creating an output path for +parent+ and source +path+.
|
140
|
+
#
|
141
|
+
# The automatically set parameter +style+ (which uses the meta information +output_path_style+
|
142
|
+
# from the path's meta information hash) defines how the output name should be built (more
|
143
|
+
# information about this in the user documentation).
|
144
|
+
def standard_output_path(parent, path, use_lang_part, style = path.meta_info['output_path_style'])
|
145
|
+
result = style.collect do |part|
|
146
|
+
case part
|
147
|
+
when String then part
|
148
|
+
when :lang then use_lang_part ? path.meta_info['lang'] : ''
|
149
|
+
when :ext then path.ext.empty? ? '' : '.' + path.ext
|
150
|
+
when :parent then temp = parent; temp = temp.parent while temp.is_fragment?; temp.path
|
151
|
+
when :year, :month, :day
|
152
|
+
ctime = path.meta_info['created_at']
|
153
|
+
if !ctime.kind_of?(Time)
|
154
|
+
raise "Invalid meta info 'created_at' for #{path}, needed because of used output path style"
|
155
|
+
end
|
156
|
+
ctime.send(part).to_s.rjust(2, '0')
|
157
|
+
when Symbol then path.send(part)
|
158
|
+
when Array then part.include?(:lang) && !use_lang_part ? '' : standard_output_path(parent, path, use_lang_part, part)
|
159
|
+
else ''
|
160
|
+
end
|
161
|
+
end
|
162
|
+
result.join('')
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
include Webgen::Loggable
|
168
|
+
include OutputPathHelpers
|
169
|
+
|
170
|
+
# Construct the output name for the given +path+ and +parent+. First it is checked if a node
|
171
|
+
# with the constructed output name already exists. If it exists, the language part is forced to
|
172
|
+
# be in the output name and the resulting output name is returned.
|
173
|
+
def output_path(parent, path)
|
174
|
+
method = path.meta_info['output_path'] + '_output_path'
|
175
|
+
use_lang_part = if path.meta_info['lang'].nil? # unlocalized files never get a lang in the filename!
|
176
|
+
false
|
177
|
+
else
|
178
|
+
Webgen::WebsiteAccess.website.config['sourcehandler.default_lang_in_output_path'] ||
|
179
|
+
Webgen::WebsiteAccess.website.config['website.lang'] != path.meta_info['lang']
|
180
|
+
end
|
181
|
+
if OutputPathHelpers.public_instance_methods(false).map(&:to_s).include?(method)
|
182
|
+
name = send(method, parent, path, use_lang_part)
|
183
|
+
name += '/' if path.path =~ /\/$/ && name !~ /\/$/
|
184
|
+
if (node = node_exists?(parent, path, name)) && node.lang == path.meta_info['lang']
|
185
|
+
name = node.path
|
186
|
+
elsif node
|
187
|
+
name = send(method, parent, path, (path.meta_info['lang'].nil? ? false : true))
|
188
|
+
name += '/' if path.path =~ /\/$/ && name !~ /\/$/
|
189
|
+
end
|
190
|
+
name
|
191
|
+
else
|
192
|
+
raise "Unknown method for creating output path: #{method}"
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
# Check if the node alcn and output path which would be created by #create_node exists. The
|
197
|
+
# +output_path+ to check for can individually be set.
|
198
|
+
def node_exists?(parent, path, output_path = self.output_path(parent, path))
|
199
|
+
parent.tree[Webgen::Node.absolute_name(parent, path.lcn, :alcn)] || (!path.meta_info['no_output'] && parent.tree[output_path, :path])
|
200
|
+
end
|
201
|
+
|
202
|
+
# Create a node under +parent+ from +path+ if it does not already exists or needs to be
|
203
|
+
# re-initialized. The found node or the newly created node is returned afterwards. +nil+ is
|
204
|
+
# returned if no node can be created (e.g. when <tt>path.meta_info['draft']</tt> is set). Some
|
205
|
+
# additional node information like <tt>:src</tt> and <tt>:processor</tt> is set and the meta
|
206
|
+
# information is checked for validness. The created/re-initialized node is yielded if a block is
|
207
|
+
# given.
|
208
|
+
def create_node(parent, path, output_path = self.output_path(parent, path))
|
209
|
+
return nil if path.meta_info['draft']
|
210
|
+
node = node_exists?(parent, path, output_path)
|
211
|
+
if node && (node.node_info[:src] != path.source_path || node.node_info[:processor] != self.class.name)
|
212
|
+
log(:warn) { "Node already exists: source = #{path.source_path} | path = #{node.path} | alcn = #{node.absolute_lcn}"}
|
213
|
+
return node
|
214
|
+
elsif !node
|
215
|
+
node = Webgen::Node.new(parent, output_path, path.cn, path.meta_info)
|
216
|
+
elsif node.flagged(:reinit)
|
217
|
+
node.reinit(output_path, path.meta_info)
|
218
|
+
else
|
219
|
+
return node
|
220
|
+
end
|
221
|
+
node['modified_at'] = Time.now unless node['modified_at'].kind_of?(Time)
|
222
|
+
node.node_info[:src] = path.source_path
|
223
|
+
node.node_info[:creation_path] = path.path
|
224
|
+
node.node_info[:processor] = self.class.name
|
225
|
+
yield(node) if block_given?
|
226
|
+
node
|
227
|
+
end
|
228
|
+
|
229
|
+
# Return the content of the given +node+. This default +content+ method just returns +nil+.
|
230
|
+
def content(node)
|
231
|
+
nil
|
232
|
+
end
|
233
|
+
|
234
|
+
# Utility method for creating a Webgen::Page object from the +path+. Also updates
|
235
|
+
# <tt>path.meta_info</tt> with the meta info from the page.
|
236
|
+
def page_from_path(path)
|
237
|
+
begin
|
238
|
+
page = Webgen::Page.from_data(path.io.data, path.meta_info)
|
239
|
+
rescue Webgen::WebgenPageFormatError => e
|
240
|
+
raise "Error reading source path <#{path}>: #{e.message}"
|
241
|
+
end
|
242
|
+
path.meta_info = page.meta_info
|
243
|
+
page
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
|
248
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Webgen::SourceHandler
|
4
|
+
|
5
|
+
# Simple source handler for copying files from the source tree, either verbatim or by applying a
|
6
|
+
# content processor.
|
7
|
+
class Copy
|
8
|
+
|
9
|
+
include Webgen::WebsiteAccess
|
10
|
+
include Base
|
11
|
+
|
12
|
+
# Create the node for +parent+ and +path+. If the +path+ has the name of a content processor as
|
13
|
+
# the first part in the extension, it is preprocessed.
|
14
|
+
def create_node(parent, path)
|
15
|
+
if path.ext.index('.')
|
16
|
+
processor, *rest = path.ext.split('.')
|
17
|
+
if website.blackboard.invoke(:content_processor_names).include?(processor)
|
18
|
+
path.ext = rest.join('.')
|
19
|
+
else
|
20
|
+
processor = nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
super(parent, path) do |node|
|
24
|
+
node.node_info[:preprocessor] = processor
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Return either the preprocessed content of the +node+ or the IO object for the node's source
|
29
|
+
# path depending on the node type.
|
30
|
+
def content(node)
|
31
|
+
io = website.blackboard.invoke(:source_paths)[node.node_info[:src]].io
|
32
|
+
if node.node_info[:preprocessor]
|
33
|
+
context = Webgen::ContentProcessor::Context.new(:content => io.data, :chain => [node])
|
34
|
+
website.blackboard.invoke(:content_processor, node.node_info[:preprocessor]).call(context)
|
35
|
+
context.content
|
36
|
+
else
|
37
|
+
io
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Webgen::SourceHandler
|
4
|
+
|
5
|
+
# Handles directory source paths.
|
6
|
+
class Directory
|
7
|
+
|
8
|
+
include Base
|
9
|
+
include Webgen::WebsiteAccess
|
10
|
+
|
11
|
+
def initialize # :nodoc:
|
12
|
+
website.blackboard.add_service(:create_directories, method(:create_directories))
|
13
|
+
end
|
14
|
+
|
15
|
+
# Recursively create the directories specified in +dirname+ under +parent+ (a leading slash is
|
16
|
+
# ignored). The path +path+ is the path that lead to the creation of these directories.
|
17
|
+
def create_directories(parent, dirname, path)
|
18
|
+
dirname.sub(/^\//, '').split('/').each do |dir|
|
19
|
+
dir_path = Webgen::Path.new(File.join(parent.absolute_lcn, dir, '/'), path)
|
20
|
+
nodes = website.blackboard.invoke(:create_nodes, parent.tree, parent.absolute_lcn,
|
21
|
+
dir_path, self) do |dir_parent, dir_path|
|
22
|
+
node_exists?(dir_parent, dir_path) || create_node(dir_parent, dir_path)
|
23
|
+
end
|
24
|
+
parent = nodes.first
|
25
|
+
end
|
26
|
+
parent
|
27
|
+
end
|
28
|
+
|
29
|
+
# Return an empty string to signal that the directory should be written to the output.
|
30
|
+
def content(node)
|
31
|
+
''
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Webgen::SourceHandler
|
4
|
+
|
5
|
+
# Source handler for creating atom and/or rss feeds.
|
6
|
+
class Feed
|
7
|
+
|
8
|
+
include Webgen::WebsiteAccess
|
9
|
+
include Base
|
10
|
+
|
11
|
+
# The mandatory keys that need to be set in a feed file.
|
12
|
+
MANDATORY_INFOS = %W[site_url author entries]
|
13
|
+
|
14
|
+
def initialize # :nodoc:
|
15
|
+
website.blackboard.add_listener(:node_changed?, method(:node_changed?))
|
16
|
+
end
|
17
|
+
|
18
|
+
# Create atom and/or rss feed files from +parent+ and +path+.
|
19
|
+
def create_node(parent, path)
|
20
|
+
page = page_from_path(path)
|
21
|
+
path.meta_info['link'] ||= parent.absolute_lcn
|
22
|
+
|
23
|
+
if MANDATORY_INFOS.any? {|t| path.meta_info[t].nil?}
|
24
|
+
raise "One of #{MANDATORY_INFOS.join('/')} information missing for feed <#{path}>"
|
25
|
+
end
|
26
|
+
|
27
|
+
create_feed_node = lambda do |type|
|
28
|
+
path.ext = type
|
29
|
+
super(parent, path) do |node|
|
30
|
+
node.node_info[:feed] = page
|
31
|
+
node.node_info[:feed_type] = type
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
nodes = []
|
36
|
+
nodes << create_feed_node['atom'] if path.meta_info['atom']
|
37
|
+
nodes << create_feed_node['rss'] if path.meta_info['rss']
|
38
|
+
|
39
|
+
nodes
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return the rendered feed represented by +node+.
|
43
|
+
def content(node)
|
44
|
+
website.cache[[:sourcehandler_feed, node.node_info[:src]]] = feed_entries(node).map {|n| n.absolute_lcn}
|
45
|
+
block_name = node.node_info[:feed_type] + '_template'
|
46
|
+
if node.node_info[:feed].blocks.has_key?(block_name)
|
47
|
+
node.node_info[:feed].blocks[block_name].
|
48
|
+
render(Webgen::ContentProcessor::Context.new(:chain => [node])).content
|
49
|
+
else
|
50
|
+
feed = (website.cache.volatile[:sourcehandler_feed] ||= {})[node.node_info[:src]] ||= build_feed_for(node)
|
51
|
+
feed.build_xml(node.node_info[:feed_type], (node.node_info[:feed_type] == 'rss' ? node['rss_version'] || 2.0 : nil))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Helper method for returning the entries for the feed node +node+.
|
56
|
+
def feed_entries(node)
|
57
|
+
nr_items = (node['number_of_entries'].to_i == 0 ? 10 : node['number_of_entries'].to_i)
|
58
|
+
patterns = [node['entries']].flatten.map {|pat| Webgen::Common.absolute_path(pat, node.parent.absolute_lcn)}
|
59
|
+
|
60
|
+
node.tree.node_access[:alcn].values.
|
61
|
+
select {|node| patterns.any? {|pat| node =~ pat} && node.node_info[:page]}.
|
62
|
+
sort {|a,b| a['modified_at'] <=> b['modified_at']}[0, nr_items]
|
63
|
+
end
|
64
|
+
|
65
|
+
#######
|
66
|
+
private
|
67
|
+
#######
|
68
|
+
|
69
|
+
# Return the populated FeedTools::Feed object for +node+.
|
70
|
+
def build_feed_for(node)
|
71
|
+
require 'feed_tools'
|
72
|
+
require 'time'
|
73
|
+
|
74
|
+
site_url = node['site_url']
|
75
|
+
|
76
|
+
feed = FeedTools::Feed.new
|
77
|
+
feed.title = node['title']
|
78
|
+
feed.description = node['description']
|
79
|
+
feed.author = node['author']
|
80
|
+
feed.author.url = node['author_url']
|
81
|
+
feed.base_uri = site_url
|
82
|
+
feed.link = File.join(site_url, node.tree[node['link']].path)
|
83
|
+
feed.id = feed.link
|
84
|
+
|
85
|
+
feed.published = (node['created_at'].kind_of?(Time) ? node['created_at'] : Time.now)
|
86
|
+
feed.updated = Time.now
|
87
|
+
feed.generator = 'webgen - Webgen::SourceHandler::Feed'
|
88
|
+
|
89
|
+
node.feed_entries.each do |entry|
|
90
|
+
item = FeedTools::FeedItem.new
|
91
|
+
item.title = entry['title']
|
92
|
+
item.link = File.join(site_url, entry.path)
|
93
|
+
item.content = entry.node_info[:page].blocks[node['content_block_name'] || 'content'].render(Webgen::ContentProcessor::Context.new(:chain => [entry])).content
|
94
|
+
item.updated = entry['modified_at']
|
95
|
+
item.published = entry['created_at'] if entry['created_at'].kind_of?(Time)
|
96
|
+
if entry['author']
|
97
|
+
item.author = entry['author']
|
98
|
+
item.author.url = entry['author_url']
|
99
|
+
end
|
100
|
+
item.id = item.link
|
101
|
+
feed << item
|
102
|
+
end
|
103
|
+
feed
|
104
|
+
end
|
105
|
+
|
106
|
+
# Check if the any of the nodes used by this feed +node+ have changed and then mark the node as
|
107
|
+
# dirty.
|
108
|
+
def node_changed?(node)
|
109
|
+
return if node.node_info[:processor] != self.class.name
|
110
|
+
entries = node.feed_entries
|
111
|
+
node.flag(:dirty) if entries.map {|n| n.absolute_lcn } != website.cache[[:sourcehandler_feed, node.node_info[:src]]] ||
|
112
|
+
entries.any? {|n| n.changed?}
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Webgen::SourceHandler
|
4
|
+
|
5
|
+
# Handles page fragment nodes and provides utility methods for parsing HTML headers and generating
|
6
|
+
# fragment nodes from them.
|
7
|
+
class Fragment
|
8
|
+
|
9
|
+
include Base
|
10
|
+
include Webgen::WebsiteAccess
|
11
|
+
|
12
|
+
HTML_HEADER_REGEXP = /<h([123456])(?:>|\s([^>]*)>)(.*?)<\/h\1\s*>/i
|
13
|
+
HTML_ATTR_REGEXP = /\s*(\w+)\s*=\s*('|")([^\2]+)\2\s*/
|
14
|
+
|
15
|
+
# Parse the string +content+ for headers +h1+, ..., +h6+ and return the found, nested sections.
|
16
|
+
#
|
17
|
+
# Only those headers are used which have an +id+ attribute set. The method returns a list of
|
18
|
+
# arrays with entries <tt>level, id, title, sub sections</tt> where <tt>sub sections</tt> is
|
19
|
+
# such a list again.
|
20
|
+
def parse_html_headers(content)
|
21
|
+
sections = []
|
22
|
+
stack = []
|
23
|
+
content.scan(HTML_HEADER_REGEXP).each do |level,attrs,title|
|
24
|
+
next if attrs.nil?
|
25
|
+
id_attr = attrs.scan(HTML_ATTR_REGEXP).find {|name,sep,value| name == 'id'}
|
26
|
+
next if id_attr.nil?
|
27
|
+
id = id_attr[2]
|
28
|
+
|
29
|
+
section = [level.to_i, id, title, []]
|
30
|
+
success = false
|
31
|
+
while !success
|
32
|
+
if stack.empty?
|
33
|
+
sections << section
|
34
|
+
stack << section
|
35
|
+
success = true
|
36
|
+
elsif stack.last.first < section.first
|
37
|
+
stack.last.last << section
|
38
|
+
stack << section
|
39
|
+
success = true
|
40
|
+
else
|
41
|
+
stack.pop
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
sections
|
46
|
+
end
|
47
|
+
|
48
|
+
# Create nested fragment nodes under +parent+ from +sections+ (which can be created using
|
49
|
+
# +parse_html_headers+). +path+ is the source path that defines the fragments. The meta
|
50
|
+
# information +in_menu+ of the fragment nodes is set to the parameter +in_menu+ and the meta
|
51
|
+
# info +sort_info+ is calculated from the base +si+ value.
|
52
|
+
def create_fragment_nodes(sections, parent, path, in_menu, si = 1000 )
|
53
|
+
sections.each do |level, id, title, sub_sections|
|
54
|
+
node = website.blackboard.invoke(:create_nodes, parent.tree, parent.absolute_lcn,
|
55
|
+
Webgen::Path.new('#' + id, path.source_path),
|
56
|
+
self) do |cn_parent, cn_path|
|
57
|
+
cn_path.meta_info['title'] = title
|
58
|
+
cn_path.meta_info['in_menu'] = in_menu
|
59
|
+
cn_path.meta_info['sort_info'] = si = si.succ
|
60
|
+
create_node(cn_parent, cn_path)
|
61
|
+
end.first
|
62
|
+
create_fragment_nodes(sub_sections, node, path, in_menu, si.succ)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|