gettalong-webgen 0.5.4.20080929
Sign up to get free protection for your applications and to get access to all the features.
- 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,41 @@
|
|
1
|
+
module Webgen::SourceHandler
|
2
|
+
|
3
|
+
# Simple source handler for copying files from the source tree, either verbatim or by applying a
|
4
|
+
# content processor.
|
5
|
+
class Copy
|
6
|
+
|
7
|
+
include Webgen::WebsiteAccess
|
8
|
+
include Base
|
9
|
+
|
10
|
+
# Create the node for +parent+ and +path+. If the +path+ has the name of a content processor in
|
11
|
+
# the extension, it is preprocessed.
|
12
|
+
def create_node(parent, path)
|
13
|
+
if path.ext.index('.')
|
14
|
+
processor, *rest = path.ext.split('.')
|
15
|
+
if website.blackboard.invoke(:content_processor_names).include?(processor)
|
16
|
+
path.ext = rest.join('.')
|
17
|
+
else
|
18
|
+
processor = nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
super(parent, path) do |node|
|
22
|
+
node.node_info[:preprocessor] = processor
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Return either the preprocessed content of the +node+ or the IO object for the node's source
|
27
|
+
# path depending on the node type.
|
28
|
+
def content(node)
|
29
|
+
io = website.blackboard.invoke(:source_paths)[node.node_info[:src]].io
|
30
|
+
if node.node_info[:preprocessor]
|
31
|
+
context = Webgen::ContentProcessor::Context.new(:content => io.data, :chain => [node])
|
32
|
+
website.blackboard.invoke(:content_processor, node.node_info[:preprocessor]).call(context)
|
33
|
+
context.content
|
34
|
+
else
|
35
|
+
io
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'webgen/sourcehandler/base'
|
2
|
+
|
3
|
+
module Webgen::SourceHandler
|
4
|
+
|
5
|
+
# Handles directory source paths.
|
6
|
+
class Directory
|
7
|
+
|
8
|
+
include Base
|
9
|
+
|
10
|
+
# Creation of directory nodes is special because once they are created, they are only deleted
|
11
|
+
# when the source path gets deleted. Otherwise, only the meta information of the node gets
|
12
|
+
# updated.
|
13
|
+
def create_node(parent, path)
|
14
|
+
if node = node_exists?(parent, path)
|
15
|
+
node.meta_info.clear
|
16
|
+
node.meta_info.update(path.meta_info)
|
17
|
+
node.dirty = true
|
18
|
+
node
|
19
|
+
else
|
20
|
+
super(parent, path)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Return an empty string to signal that the directory should be written to the output.
|
25
|
+
def content(node)
|
26
|
+
''
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'webgen/websiteaccess'
|
2
|
+
require 'webgen/sourcehandler/base'
|
3
|
+
|
4
|
+
module Webgen::SourceHandler
|
5
|
+
|
6
|
+
# Source handler for creating atom and/or rss feeds.
|
7
|
+
class Feed
|
8
|
+
|
9
|
+
include Webgen::WebsiteAccess
|
10
|
+
include Base
|
11
|
+
|
12
|
+
# The mandatory keys that need to be set in a feed file.
|
13
|
+
MANDATORY_INFOS = %W[site_url author entries]
|
14
|
+
|
15
|
+
def initialize # :nodoc:
|
16
|
+
website.blackboard.add_listener(:node_changed?, method(:node_changed?))
|
17
|
+
end
|
18
|
+
|
19
|
+
# Create atom and/or rss feed files from +parent+ and +path+.
|
20
|
+
def create_node(parent, path)
|
21
|
+
page = page_from_path(path)
|
22
|
+
path.meta_info['link'] ||= parent.absolute_lcn
|
23
|
+
|
24
|
+
if MANDATORY_INFOS.any? {|t| path.meta_info[t].nil?}
|
25
|
+
raise "One of #{MANDATORY_INFOS.join('/')} information missing for feed <#{path}>"
|
26
|
+
end
|
27
|
+
|
28
|
+
create_feed_node = lambda do |type|
|
29
|
+
path.ext = type
|
30
|
+
super(parent, path) do |node|
|
31
|
+
node.node_info[:feed] = page
|
32
|
+
node.node_info[:feed_type] = type
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
nodes = []
|
37
|
+
nodes << create_feed_node['atom'] if path.meta_info['atom']
|
38
|
+
nodes << create_feed_node['rss'] if path.meta_info['rss']
|
39
|
+
|
40
|
+
nodes
|
41
|
+
end
|
42
|
+
|
43
|
+
# Return the rendered feed represented by +node+.
|
44
|
+
def content(node)
|
45
|
+
website.cache[[:sourcehandler_feed, node.node_info[:src]]] = feed_entries(node).map {|n| n.absolute_lcn}
|
46
|
+
block_name = node.node_info[:feed_type] + '_template'
|
47
|
+
if node.node_info[:feed].blocks.has_key?(block_name)
|
48
|
+
node.node_info[:feed].blocks[block_name].
|
49
|
+
render(Webgen::ContentProcessor::Context.new(:chain => [node])).content
|
50
|
+
else
|
51
|
+
feed = (website.cache.volatile[:sourcehandler_feed] ||= {})[node.node_info[:src]] ||= build_feed_for(node)
|
52
|
+
feed.feed_type = node.node_info[:feed_type]
|
53
|
+
feed.build_xml
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Helper method for returning the entries for the feed node +node+.
|
58
|
+
def feed_entries(node)
|
59
|
+
nr_items = (node['number_of_entries'].to_i == 0 ? 10 : node['number_of_entries'].to_i)
|
60
|
+
patterns = [node['entries']].flatten.map {|pat| Pathname.new(pat =~ /^\// ? pat : File.join(node.parent.absolute_lcn, pat)).cleanpath.to_s}
|
61
|
+
|
62
|
+
node.tree.node_access[:alcn].values.
|
63
|
+
select {|node| patterns.any? {|pat| node =~ pat} && node.node_info[:page]}.
|
64
|
+
sort {|a,b| a['modified_at'] <=> b['modified_at']}.
|
65
|
+
reverse[0, nr_items]
|
66
|
+
end
|
67
|
+
|
68
|
+
#######
|
69
|
+
private
|
70
|
+
#######
|
71
|
+
|
72
|
+
# Return the populated FeedTools::Feed object for +node+.
|
73
|
+
def build_feed_for(node)
|
74
|
+
require 'feed_tools'
|
75
|
+
require 'time'
|
76
|
+
|
77
|
+
site_url = node['site_url']
|
78
|
+
|
79
|
+
feed = FeedTools::Feed.new
|
80
|
+
feed.title = node['title']
|
81
|
+
feed.description = node['description']
|
82
|
+
feed.author = node['author']
|
83
|
+
feed.author.url = node['author_url']
|
84
|
+
feed.base_uri = site_url
|
85
|
+
feed.link = File.join(site_url, node.tree[node['link']].path)
|
86
|
+
feed.id = feed.link
|
87
|
+
|
88
|
+
feed.published = (node['created_at'].kind_of?(Time) ? node['created_at'] : Time.now)
|
89
|
+
feed.updated = Time.now
|
90
|
+
feed.generator = 'webgen - Webgen::SourceHandler::Feed'
|
91
|
+
feed.icon = File.join(site_url, node.tree[node['icon']].path) if node['icon']
|
92
|
+
|
93
|
+
node.feed_entries.each do |entry|
|
94
|
+
item = FeedTools::FeedItem.new
|
95
|
+
item.title = entry['title']
|
96
|
+
item.link = File.join(site_url, entry.path)
|
97
|
+
item.content = entry.node_info[:page].blocks['content'].render(Webgen::ContentProcessor::Context.new(:chain => [entry])).content
|
98
|
+
item.updated = entry['modified_at']
|
99
|
+
item.published = entry['created_at'] if entry['created_at'].kind_of?(Time)
|
100
|
+
if entry['author']
|
101
|
+
item.author = entry['author']
|
102
|
+
item.author.url = entry['author_url']
|
103
|
+
end
|
104
|
+
item.id = item.link
|
105
|
+
feed << item
|
106
|
+
end
|
107
|
+
feed
|
108
|
+
end
|
109
|
+
|
110
|
+
# Check if the +node+ has meta information from any meta info node and if so, if the meta info
|
111
|
+
# node in question has changed.
|
112
|
+
def node_changed?(node)
|
113
|
+
return if node.node_info[:processor] != self.class.name
|
114
|
+
entries = node.feed_entries
|
115
|
+
node.dirty = true if entries.map {|n| n.absolute_lcn } != website.cache[[:sourcehandler_feed, node.node_info[:src]]] ||
|
116
|
+
entries.any? {|n| n.changed?}
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'webgen/sourcehandler/base'
|
2
|
+
require 'webgen/websiteaccess'
|
3
|
+
|
4
|
+
module Webgen::SourceHandler
|
5
|
+
|
6
|
+
# Handles page fragment nodes and provides utility methods for parsing HTML headers and generating
|
7
|
+
# fragment nodes from them.
|
8
|
+
class Fragment
|
9
|
+
|
10
|
+
include Base
|
11
|
+
include Webgen::WebsiteAccess
|
12
|
+
|
13
|
+
HTML_HEADER_REGEXP = /<h([123456])(?:>|\s([^>]*)>)(.*?)<\/h\1\s*>/i
|
14
|
+
HTML_ATTR_REGEXP = /\s*(\w+)\s*=\s*('|")([^\2]+)\2\s*/
|
15
|
+
|
16
|
+
# Parse the string +content+ for headers +h1+, ..., +h6+ and return the found, nested sections.
|
17
|
+
#
|
18
|
+
# Only those headers are used which have an +id+ attribute set. The method returns a list of
|
19
|
+
# arrays with entries <tt>level, id, title, sub sections</tt> where <tt>sub sections</tt> is
|
20
|
+
# such a list again.
|
21
|
+
def parse_html_headers(content)
|
22
|
+
sections = []
|
23
|
+
stack = []
|
24
|
+
content.scan(HTML_HEADER_REGEXP).each do |level,attrs,title|
|
25
|
+
next if attrs.nil?
|
26
|
+
id_attr = attrs.scan(HTML_ATTR_REGEXP).find {|name,sep,value| name == 'id'}
|
27
|
+
next if id_attr.nil?
|
28
|
+
id = id_attr[2]
|
29
|
+
|
30
|
+
section = [level.to_i, id, title, []]
|
31
|
+
success = false
|
32
|
+
while !success
|
33
|
+
if stack.empty?
|
34
|
+
sections << section
|
35
|
+
stack << section
|
36
|
+
success = true
|
37
|
+
elsif stack.last.first < section.first
|
38
|
+
stack.last.last << section
|
39
|
+
stack << section
|
40
|
+
success = true
|
41
|
+
else
|
42
|
+
stack.pop
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
sections
|
47
|
+
end
|
48
|
+
|
49
|
+
# Create nested fragment nodes under +parent+ from +sections+ (which can be created using
|
50
|
+
# +parse_html_headers+). +path+ is the source path that defines the fragments. The meta
|
51
|
+
# information +in_menu+ of the fragment nodes is set to the parameter +in_menu+ and the meta
|
52
|
+
# info +sort_info+ is calculated from the base +si+ value.
|
53
|
+
def create_fragment_nodes(sections, parent, path, in_menu, si = 1000 )
|
54
|
+
sections.each do |level, id, title, sub_sections|
|
55
|
+
node = website.blackboard.invoke(:create_nodes, parent.tree, parent.absolute_lcn,
|
56
|
+
path, self) do |cn_parent, cn_path|
|
57
|
+
ptemp = Webgen::Path.new('#' + id)
|
58
|
+
ptemp.meta_info = cn_path.meta_info.merge(ptemp.meta_info)
|
59
|
+
create_node(cn_parent, ptemp)
|
60
|
+
end.first
|
61
|
+
node['title'] = title
|
62
|
+
node['in_menu'] = in_menu
|
63
|
+
node['sort_info'] = si = si.succ
|
64
|
+
node.node_info[:src] = path.path
|
65
|
+
create_fragment_nodes(sub_sections, node, path, in_menu, si.succ)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'yaml'
|
3
|
+
require 'webgen/sourcehandler/base'
|
4
|
+
require 'webgen/websiteaccess'
|
5
|
+
|
6
|
+
module Webgen::SourceHandler
|
7
|
+
|
8
|
+
# Handles meta information files which provide meta information for other files.
|
9
|
+
class Metainfo
|
10
|
+
|
11
|
+
include Base
|
12
|
+
include Webgen::WebsiteAccess
|
13
|
+
|
14
|
+
CKEY = [:metainfo, :nodes]
|
15
|
+
|
16
|
+
# Upon creation the object registers itself as listener for some node hooks.
|
17
|
+
def initialize
|
18
|
+
website.blackboard.add_listener(:node_meta_info_changed?, method(:node_meta_info_changed?))
|
19
|
+
website.blackboard.add_listener(:before_node_created, method(:before_node_created))
|
20
|
+
website.blackboard.add_listener(:before_node_deleted, method(:before_node_deleted))
|
21
|
+
website.blackboard.add_listener(:after_node_created, method(:after_node_created))
|
22
|
+
self.nodes ||= Set.new
|
23
|
+
end
|
24
|
+
|
25
|
+
# Create a meta info node from +parent+ and +path+.
|
26
|
+
def create_node(parent, path)
|
27
|
+
page = page_from_path(path)
|
28
|
+
super(parent, path) do |node|
|
29
|
+
[[:mi_paths, 'paths'], [:mi_alcn, 'alcn']].each do |mi_key, block_name|
|
30
|
+
node.node_info[mi_key] = {}
|
31
|
+
YAML::load(page.blocks[block_name].content).each do |key, value|
|
32
|
+
key = Pathname.new(key =~ /^\// ? key : File.join(parent.absolute_lcn, key)).cleanpath.to_s
|
33
|
+
key.chomp('/') unless key == '/'
|
34
|
+
node.node_info[mi_key][key] = value
|
35
|
+
end if page.blocks.has_key?(block_name)
|
36
|
+
end
|
37
|
+
website.cache[[:sh_metainfo_node_mi, node.absolute_lcn]] = {
|
38
|
+
:mi_paths => node.node_info[:mi_paths],
|
39
|
+
:mi_alcn => node.node_info[:mi_alcn]
|
40
|
+
}
|
41
|
+
|
42
|
+
mark_all_matched_dirty(node)
|
43
|
+
|
44
|
+
self.nodes << node
|
45
|
+
self.nodes = self.nodes.sort_by {|n| n.absolute_lcn}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def nodes #:nodoc:
|
50
|
+
website.cache.permanent[CKEY]
|
51
|
+
end
|
52
|
+
|
53
|
+
def nodes=(val) #:nodoc:
|
54
|
+
website.cache.permanent[CKEY] = val
|
55
|
+
end
|
56
|
+
|
57
|
+
#######
|
58
|
+
private
|
59
|
+
#######
|
60
|
+
|
61
|
+
# Return +true+ if any meta information for +node+ provided by +mi_node+ has changed.
|
62
|
+
def meta_info_changed?(mi_node, node, use_cache = true)
|
63
|
+
use_cache = false if !website.cache.old_data[[:sh_metainfo_node_mi, mi_node.absolute_lcn]]
|
64
|
+
cached = website.cache[[:sh_metainfo_node_mi, mi_node.absolute_lcn]]
|
65
|
+
path = website.blackboard.invoke(:source_paths)[node.node_info[:src]]
|
66
|
+
(mi_node.node_info[:mi_paths].any? {|pattern, mi| path =~ pattern && (!use_cache || mi != cached[:mi_paths][pattern])} ||
|
67
|
+
mi_node.node_info[:mi_alcn].any? {|pattern, mi| node =~ pattern && (!use_cache || mi != cached[:mi_alcn][pattern])})
|
68
|
+
end
|
69
|
+
|
70
|
+
# Mark all nodes that are matched by a path or an alcn specifcation in the meta info node +node+
|
71
|
+
# as dirty.
|
72
|
+
def mark_all_matched_dirty(node, use_cache = true)
|
73
|
+
node.tree.node_access[:alcn].each do |path, n|
|
74
|
+
n.dirty_meta_info = true if meta_info_changed?(node, n, use_cache)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Update the meta info of matched path before a node is created.
|
79
|
+
def before_node_created(parent, path)
|
80
|
+
self.nodes.each do |node|
|
81
|
+
node.node_info[:mi_paths].each do |pattern, mi|
|
82
|
+
path.meta_info.update(mi) if path =~ pattern
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Update the meta information of a matched alcn after the node has been created.
|
88
|
+
def after_node_created(node)
|
89
|
+
self.nodes.each do |n|
|
90
|
+
n.node_info[:mi_alcn].each do |pattern, mi|
|
91
|
+
node.meta_info.update(mi) if node =~ pattern
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Check if the +node+ has meta information from any meta info node and if so, if the meta info
|
97
|
+
# node in question has changed.
|
98
|
+
def node_meta_info_changed?(node)
|
99
|
+
return if self.nodes.include?(node)
|
100
|
+
self.nodes.each do |n|
|
101
|
+
if n.created && meta_info_changed?(n, node)
|
102
|
+
node.dirty_meta_info = true
|
103
|
+
return
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Delete the meta info node +node+ from the internal array.
|
109
|
+
def before_node_deleted(node)
|
110
|
+
return unless node.node_info[:processor] == self.class.name
|
111
|
+
mark_all_matched_dirty(node, false) if !website.blackboard.invoke(:source_paths).include?(node.node_info[:src])
|
112
|
+
self.nodes.delete(node)
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'webgen/websiteaccess'
|
2
|
+
require 'webgen/sourcehandler/base'
|
3
|
+
|
4
|
+
module Webgen::SourceHandler
|
5
|
+
|
6
|
+
# Source handler for handling content files in Webgen Page Format.
|
7
|
+
class Page
|
8
|
+
|
9
|
+
include Webgen::WebsiteAccess
|
10
|
+
include Base
|
11
|
+
|
12
|
+
def initialize #:nodoc:
|
13
|
+
website.blackboard.add_listener(:node_meta_info_changed?, method(:meta_info_changed?))
|
14
|
+
end
|
15
|
+
|
16
|
+
# Create a page file from +parent+ and +path+.
|
17
|
+
def create_node(parent, path)
|
18
|
+
page = page_from_path(path)
|
19
|
+
path.meta_info['lang'] ||= website.config['website.lang']
|
20
|
+
path.ext = 'html' if path.ext == 'page'
|
21
|
+
|
22
|
+
super(parent, path) do |node|
|
23
|
+
website.cache[[:sh_page_node_mi, node.absolute_lcn]] = node.meta_info.dup
|
24
|
+
|
25
|
+
node.node_info[:page] = page
|
26
|
+
tmp_logger = website.logger
|
27
|
+
website.logger = nil # disabling logging whiling creating fragment nodes
|
28
|
+
|
29
|
+
website.cache.permanent[:page_sections] ||= {}
|
30
|
+
sections = if path.changed? || !website.cache.permanent[:page_sections][node.absolute_lcn]
|
31
|
+
website.blackboard.invoke(:parse_html_headers, render_node(node, 'content', []))
|
32
|
+
else
|
33
|
+
website.cache.permanent[:page_sections][node.absolute_lcn]
|
34
|
+
end
|
35
|
+
website.cache.permanent[:page_sections][node.absolute_lcn] = sections
|
36
|
+
website.blackboard.invoke(:create_fragment_nodes,
|
37
|
+
sections,
|
38
|
+
node, website.blackboard.invoke(:source_paths)[path.path],
|
39
|
+
node.meta_info['fragments_in_menu'])
|
40
|
+
website.logger = tmp_logger
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Render the block called +block_name+ of the given +node+. The parameter +templates+ is set to
|
45
|
+
# the default template chain for the given +node+ but you can assign a custom template chain (an
|
46
|
+
# array of template nodes) if need arises. Return +nil+ if an error occurred.
|
47
|
+
def render_node(node, block_name = 'content', templates = website.blackboard.invoke(:templates_for_node, node))
|
48
|
+
chain = [templates, node].flatten
|
49
|
+
|
50
|
+
if chain.first.node_info[:page].blocks.has_key?(block_name)
|
51
|
+
node.node_info[:used_nodes] << chain.first.absolute_lcn
|
52
|
+
context = chain.first.node_info[:page].blocks[block_name].render(Webgen::ContentProcessor::Context.new(:chain => chain))
|
53
|
+
context.content
|
54
|
+
else
|
55
|
+
raise "Error rendering <#{node.absolute_lcn}>: no block named '#{block_name}' in <#{chain.first.absolute_lcn}>"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
alias_method :content, :render_node
|
59
|
+
|
60
|
+
#######
|
61
|
+
private
|
62
|
+
#######
|
63
|
+
|
64
|
+
# Checks if the meta information provided by the file in Webgen Page Format changed.
|
65
|
+
def meta_info_changed?(node)
|
66
|
+
return if !node.created || node.node_info[:processor] != self.class.name
|
67
|
+
ckey = [:sh_page_node_mi, node.absolute_lcn]
|
68
|
+
old_mi = website.cache.old_data[ckey]
|
69
|
+
old_mi.delete('modified_at') if old_mi
|
70
|
+
new_mi = website.cache.new_data[ckey]
|
71
|
+
new_mi.delete('modified_at')
|
72
|
+
node.dirty_meta_info = true if old_mi != new_mi
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|