gettalong-webgen 0.5.4.20080929
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/AUTHORS +5 -0
- data/COPYING +10 -0
- data/GPL +340 -0
- data/Rakefile +324 -0
- data/THANKS +17 -0
- data/bin/webgen +10 -0
- data/data/webgen/resources.yaml +3 -0
- data/data/webgen/webgui/controller/main.rb +129 -0
- data/data/webgen/webgui/overrides/win32console.rb +0 -0
- data/data/webgen/webgui/public/css/jquery.autocomplete.css +50 -0
- data/data/webgen/webgui/public/css/ramaze_error.css +90 -0
- data/data/webgen/webgui/public/css/style.css +55 -0
- data/data/webgen/webgui/public/img/headerbg.jpg +0 -0
- data/data/webgen/webgui/public/img/webgen_logo.png +0 -0
- data/data/webgen/webgui/public/js/jquery.autocomplete.js +15 -0
- data/data/webgen/webgui/public/js/jquery.js +32 -0
- data/data/webgen/webgui/view/create_website.xhtml +22 -0
- data/data/webgen/webgui/view/error.xhtml +64 -0
- data/data/webgen/webgui/view/index.xhtml +22 -0
- data/data/webgen/webgui/view/manage_website.xhtml +18 -0
- data/data/webgen/webgui/view/page.xhtml +40 -0
- data/data/webgen/website_skeleton/README +10 -0
- data/data/webgen/website_skeleton/Rakefile +40 -0
- data/data/webgen/website_skeleton/config.yaml +17 -0
- data/data/webgen/website_skeleton/ext/init.rb +6 -0
- data/data/webgen/website_styles/1024px/README +13 -0
- data/data/webgen/website_styles/1024px/src/default.css +188 -0
- data/data/webgen/website_styles/1024px/src/default.template +60 -0
- data/data/webgen/website_styles/1024px/src/images/background.gif +0 -0
- data/data/webgen/website_styles/andreas00/README +13 -0
- data/data/webgen/website_styles/andreas00/src/default.css +290 -0
- data/data/webgen/website_styles/andreas00/src/default.template +60 -0
- data/data/webgen/website_styles/andreas00/src/images/bg.gif +0 -0
- data/data/webgen/website_styles/andreas00/src/images/front.jpg +0 -0
- data/data/webgen/website_styles/andreas00/src/images/menubg.gif +0 -0
- data/data/webgen/website_styles/andreas00/src/images/menubg2.gif +0 -0
- data/data/webgen/website_styles/andreas01/README +14 -0
- data/data/webgen/website_styles/andreas01/src/default.css +310 -0
- data/data/webgen/website_styles/andreas01/src/default.template +61 -0
- data/data/webgen/website_styles/andreas01/src/images/bg.gif +0 -0
- data/data/webgen/website_styles/andreas01/src/images/front.jpg +0 -0
- data/data/webgen/website_styles/andreas01/src/print.css +35 -0
- data/data/webgen/website_styles/andreas03/README +14 -0
- data/data/webgen/website_styles/andreas03/src/default.css +223 -0
- data/data/webgen/website_styles/andreas03/src/default.template +58 -0
- data/data/webgen/website_styles/andreas03/src/images/bodybg.png +0 -0
- data/data/webgen/website_styles/andreas03/src/images/contbg.png +0 -0
- data/data/webgen/website_styles/andreas03/src/images/footerbg.png +0 -0
- data/data/webgen/website_styles/andreas03/src/images/gradient1.png +0 -0
- data/data/webgen/website_styles/andreas03/src/images/gradient2.png +0 -0
- data/data/webgen/website_styles/andreas04/README +15 -0
- data/data/webgen/website_styles/andreas04/src/default.css +290 -0
- data/data/webgen/website_styles/andreas04/src/default.template +81 -0
- data/data/webgen/website_styles/andreas04/src/images/blinkarrow.gif +0 -0
- data/data/webgen/website_styles/andreas04/src/images/bodybg.png +0 -0
- data/data/webgen/website_styles/andreas04/src/images/contentbg.png +0 -0
- data/data/webgen/website_styles/andreas04/src/images/entrybg.png +0 -0
- data/data/webgen/website_styles/andreas04/src/images/flash.gif +0 -0
- data/data/webgen/website_styles/andreas04/src/images/flash2.gif +0 -0
- data/data/webgen/website_styles/andreas04/src/images/globe.gif +0 -0
- data/data/webgen/website_styles/andreas04/src/images/globebottom.gif +0 -0
- data/data/webgen/website_styles/andreas04/src/images/linkarrow.gif +0 -0
- data/data/webgen/website_styles/andreas04/src/images/menuhover.png +0 -0
- data/data/webgen/website_styles/andreas05/README +14 -0
- data/data/webgen/website_styles/andreas05/src/default.css +33 -0
- data/data/webgen/website_styles/andreas05/src/default.template +40 -0
- data/data/webgen/website_styles/andreas05/src/images/bodybg.gif +0 -0
- data/data/webgen/website_styles/andreas05/src/images/front.png +0 -0
- data/data/webgen/website_styles/andreas06/README +14 -0
- data/data/webgen/website_styles/andreas06/src/default.css +354 -0
- data/data/webgen/website_styles/andreas06/src/default.template +70 -0
- data/data/webgen/website_styles/andreas06/src/images/bodybg.gif +0 -0
- data/data/webgen/website_styles/andreas06/src/images/boxbg.gif +0 -0
- data/data/webgen/website_styles/andreas06/src/images/greypx.gif +0 -0
- data/data/webgen/website_styles/andreas06/src/images/header.jpg +0 -0
- data/data/webgen/website_styles/andreas06/src/images/innerbg.gif +0 -0
- data/data/webgen/website_styles/andreas06/src/images/leaves.jpg +0 -0
- data/data/webgen/website_styles/andreas06/src/images/tabs.gif +0 -0
- data/data/webgen/website_styles/andreas07/README +15 -0
- data/data/webgen/website_styles/andreas07/src/browserfix.css +7 -0
- data/data/webgen/website_styles/andreas07/src/default.css +92 -0
- data/data/webgen/website_styles/andreas07/src/default.template +42 -0
- data/data/webgen/website_styles/andreas07/src/images/bodybg.gif +0 -0
- data/data/webgen/website_styles/andreas07/src/images/sidebarbg.gif +0 -0
- data/data/webgen/website_styles/andreas08/README +14 -0
- data/data/webgen/website_styles/andreas08/src/default.css +224 -0
- data/data/webgen/website_styles/andreas08/src/default.template +51 -0
- data/data/webgen/website_styles/andreas09/README +14 -0
- data/data/webgen/website_styles/andreas09/src/default.css +308 -0
- data/data/webgen/website_styles/andreas09/src/default.template +68 -0
- data/data/webgen/website_styles/andreas09/src/images/bodybg-black.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/bodybg-green.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/bodybg-orange.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/bodybg-purple.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/bodybg-red.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/bodybg.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/footerbg.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/menuhover-black.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/menuhover-green.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/menuhover-orange.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/menuhover-purple.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/menuhover-red.jpg +0 -0
- data/data/webgen/website_styles/andreas09/src/images/menuhover.jpg +0 -0
- data/data/webgen/website_styles/simple/README +6 -0
- data/data/webgen/website_styles/simple/src/default.css +84 -0
- data/data/webgen/website_styles/simple/src/default.template +36 -0
- data/data/webgen/website_templates/default/README +6 -0
- data/data/webgen/website_templates/default/src/index.page +8 -0
- data/data/webgen/website_templates/project/README +5 -0
- data/data/webgen/website_templates/project/src/about.page +12 -0
- data/data/webgen/website_templates/project/src/download.page +15 -0
- data/data/webgen/website_templates/project/src/features.page +8 -0
- data/data/webgen/website_templates/project/src/index.page +9 -0
- data/data/webgen/website_templates/project/src/screenshots.page +18 -0
- data/doc/contentprocessor.template +11 -0
- data/doc/contentprocessor/blocks.page +66 -0
- data/doc/contentprocessor/builder.page +80 -0
- data/doc/contentprocessor/erb.page +56 -0
- data/doc/contentprocessor/erubis.page +46 -0
- data/doc/contentprocessor/haml.page +47 -0
- data/doc/contentprocessor/maruku.page +41 -0
- data/doc/contentprocessor/rdiscount.page +37 -0
- data/doc/contentprocessor/rdoc.page +36 -0
- data/doc/contentprocessor/redcloth.page +39 -0
- data/doc/contentprocessor/sass.page +31 -0
- data/doc/contentprocessor/tags.page +73 -0
- data/doc/extensions.metainfo +29 -0
- data/doc/extensions.page +16 -0
- data/doc/extensions.template +17 -0
- data/doc/faq.page +214 -0
- data/doc/getting_started.page +134 -0
- data/doc/index.page +65 -0
- data/doc/manual.page +532 -0
- data/doc/reference_configuration.page +646 -0
- data/doc/reference_metainfo.page +213 -0
- data/doc/sourcehandler.template +21 -0
- data/doc/sourcehandler/copy.page +19 -0
- data/doc/sourcehandler/directory.page +27 -0
- data/doc/sourcehandler/feed.page +82 -0
- data/doc/sourcehandler/metainfo.page +41 -0
- data/doc/sourcehandler/page.page +30 -0
- data/doc/sourcehandler/sitemap.page +46 -0
- data/doc/sourcehandler/template.page +45 -0
- data/doc/sourcehandler/virtual.page +49 -0
- data/doc/tag.template +25 -0
- data/doc/tag/breadcrumbtrail.page +40 -0
- data/doc/tag/coderay.page +49 -0
- data/doc/tag/date.page +31 -0
- data/doc/tag/executecommand.page +26 -0
- data/doc/tag/includefile.page +32 -0
- data/doc/tag/langbar.page +22 -0
- data/doc/tag/menu.page +92 -0
- data/doc/tag/metainfo.page +29 -0
- data/doc/tag/relocatable.page +38 -0
- data/doc/tag/sitemap.page +31 -0
- data/doc/upgrading.page +139 -0
- data/doc/webgen_page_format.page +128 -0
- data/lib/webgen/blackboard.rb +73 -0
- data/lib/webgen/cache.rb +85 -0
- data/lib/webgen/cli.rb +118 -0
- data/lib/webgen/cli/create_command.rb +64 -0
- data/lib/webgen/cli/run_command.rb +20 -0
- data/lib/webgen/cli/utils.rb +86 -0
- data/lib/webgen/cli/webgui_command.rb +49 -0
- data/lib/webgen/common.rb +10 -0
- data/lib/webgen/common/sitemap.rb +76 -0
- data/lib/webgen/configuration.rb +147 -0
- data/lib/webgen/contentprocessor.rb +96 -0
- data/lib/webgen/contentprocessor/blocks.rb +46 -0
- data/lib/webgen/contentprocessor/builder.rb +26 -0
- data/lib/webgen/contentprocessor/context.rb +90 -0
- data/lib/webgen/contentprocessor/erb.rb +24 -0
- data/lib/webgen/contentprocessor/erubis.rb +40 -0
- data/lib/webgen/contentprocessor/haml.rb +25 -0
- data/lib/webgen/contentprocessor/maruku.rb +18 -0
- data/lib/webgen/contentprocessor/rdiscount.rb +15 -0
- data/lib/webgen/contentprocessor/rdoc.rb +17 -0
- data/lib/webgen/contentprocessor/redcloth.rb +15 -0
- data/lib/webgen/contentprocessor/sass.rb +18 -0
- data/lib/webgen/contentprocessor/tags.rb +134 -0
- data/lib/webgen/coreext.rb +10 -0
- data/lib/webgen/default_config.rb +198 -0
- data/lib/webgen/languages.rb +578 -0
- data/lib/webgen/loggable.rb +23 -0
- data/lib/webgen/logger.rb +78 -0
- data/lib/webgen/node.rb +347 -0
- data/lib/webgen/output.rb +37 -0
- data/lib/webgen/output/filesystem.rb +67 -0
- data/lib/webgen/page.rb +133 -0
- data/lib/webgen/path.rb +182 -0
- data/lib/webgen/source.rb +24 -0
- data/lib/webgen/source/filesystem.rb +58 -0
- data/lib/webgen/source/resource.rb +42 -0
- data/lib/webgen/source/stacked.rb +53 -0
- data/lib/webgen/sourcehandler.rb +202 -0
- data/lib/webgen/sourcehandler/base.rb +211 -0
- data/lib/webgen/sourcehandler/copy.rb +41 -0
- data/lib/webgen/sourcehandler/directory.rb +31 -0
- data/lib/webgen/sourcehandler/feed.rb +121 -0
- data/lib/webgen/sourcehandler/fragment.rb +71 -0
- data/lib/webgen/sourcehandler/metainfo.rb +117 -0
- data/lib/webgen/sourcehandler/page.rb +77 -0
- data/lib/webgen/sourcehandler/sitemap.rb +60 -0
- data/lib/webgen/sourcehandler/template.rb +68 -0
- data/lib/webgen/sourcehandler/virtual.rb +75 -0
- data/lib/webgen/tag.rb +23 -0
- data/lib/webgen/tag/base.rb +162 -0
- data/lib/webgen/tag/breadcrumbtrail.rb +71 -0
- data/lib/webgen/tag/coderay.rb +32 -0
- data/lib/webgen/tag/date.rb +18 -0
- data/lib/webgen/tag/executecommand.rb +29 -0
- data/lib/webgen/tag/includefile.rb +42 -0
- data/lib/webgen/tag/langbar.rb +52 -0
- data/lib/webgen/tag/menu.rb +186 -0
- data/lib/webgen/tag/metainfo.rb +25 -0
- data/lib/webgen/tag/relocatable.rb +53 -0
- data/lib/webgen/tag/sitemap.rb +42 -0
- data/lib/webgen/tree.rb +80 -0
- data/lib/webgen/version.rb +6 -0
- data/lib/webgen/webgentask.rb +148 -0
- data/lib/webgen/website.rb +214 -0
- data/lib/webgen/websiteaccess.rb +29 -0
- data/lib/webgen/websitemanager.rb +125 -0
- data/man/man1/webgen.1 +67 -0
- data/misc/default.css +360 -0
- data/misc/default.template +75 -0
- data/misc/htmldoc.metainfo +25 -0
- data/misc/htmldoc.virtual +5 -0
- data/misc/images/arrow.gif +0 -0
- data/misc/images/error.gif +0 -0
- data/misc/images/exclamation.gif +0 -0
- data/misc/images/headerbg.jpg +0 -0
- data/misc/images/information.gif +0 -0
- data/misc/images/quote.gif +0 -0
- data/setup.rb +1585 -0
- data/test/helper.rb +41 -0
- data/test/test_blackboard.rb +58 -0
- data/test/test_cache.rb +57 -0
- data/test/test_common_sitemap.rb +56 -0
- data/test/test_configuration.rb +66 -0
- data/test/test_contentprocessor.rb +31 -0
- data/test/test_contentprocessor_blocks.rb +34 -0
- data/test/test_contentprocessor_builder.rb +19 -0
- data/test/test_contentprocessor_context.rb +38 -0
- data/test/test_contentprocessor_erb.rb +20 -0
- data/test/test_contentprocessor_erubis.rb +47 -0
- data/test/test_contentprocessor_haml.rb +20 -0
- data/test/test_contentprocessor_maruku.rb +27 -0
- data/test/test_contentprocessor_rdiscount.rb +15 -0
- data/test/test_contentprocessor_rdoc.rb +16 -0
- data/test/test_contentprocessor_redcloth.rb +12 -0
- data/test/test_contentprocessor_sass.rb +20 -0
- data/test/test_contentprocessor_tags.rb +97 -0
- data/test/test_languages.rb +53 -0
- data/test/test_loggable.rb +30 -0
- data/test/test_logger.rb +73 -0
- data/test/test_node.rb +339 -0
- data/test/test_output_filesystem.rb +58 -0
- data/test/test_page.rb +203 -0
- data/test/test_path.rb +131 -0
- data/test/test_source_filesystem.rb +59 -0
- data/test/test_source_resource.rb +26 -0
- data/test/test_source_stacked.rb +34 -0
- data/test/test_sourcehandler_base.rb +92 -0
- data/test/test_sourcehandler_copy.rb +45 -0
- data/test/test_sourcehandler_directory.rb +25 -0
- data/test/test_sourcehandler_feed.rb +74 -0
- data/test/test_sourcehandler_fragment.rb +67 -0
- data/test/test_sourcehandler_metainfo.rb +93 -0
- data/test/test_sourcehandler_page.rb +70 -0
- data/test/test_sourcehandler_sitemap.rb +47 -0
- data/test/test_sourcehandler_template.rb +63 -0
- data/test/test_sourcehandler_virtual.rb +56 -0
- data/test/test_tag_base.rb +82 -0
- data/test/test_tag_breadcrumbtrail.rb +89 -0
- data/test/test_tag_coderay.rb +30 -0
- data/test/test_tag_date.rb +16 -0
- data/test/test_tag_executecommand.rb +39 -0
- data/test/test_tag_includefile.rb +48 -0
- data/test/test_tag_langbar.rb +60 -0
- data/test/test_tag_menu.rb +195 -0
- data/test/test_tag_metainfo.rb +17 -0
- data/test/test_tag_relocatable.rb +57 -0
- data/test/test_tag_sitemap.rb +44 -0
- data/test/test_tree.rb +69 -0
- data/test/test_webgentask.rb +21 -0
- data/test/test_website.rb +96 -0
- data/test/test_websiteaccess.rb +23 -0
- data/test/test_websitemanager.rb +68 -0
- metadata +575 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'webgen/websiteaccess'
|
2
|
+
|
3
|
+
module Webgen
|
4
|
+
|
5
|
+
# This module should be included in all classes that need a logging facility.
|
6
|
+
module Loggable
|
7
|
+
|
8
|
+
# Log the result of the +block+ using the log level +log_level+.
|
9
|
+
def log(sev_level, &block)
|
10
|
+
source = (self.kind_of?(Class) ? self.name : self.class.name) + '#' + caller[0][%r"`.*"][1..-2]
|
11
|
+
if WebsiteAccess.website && WebsiteAccess.website.logger && (!WebsiteAccess.website.config['logger.mask'] || source =~ WebsiteAccess.website.config['logger.mask'])
|
12
|
+
WebsiteAccess.website.logger.send(sev_level, source, &block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Shortcut for writing a line to the normal log output.
|
17
|
+
def puts(*args)
|
18
|
+
(args.last == :verbose ? log(:verbose) { args[0..-2].join } : log(:stdout) { args.join })
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
module Webgen
|
5
|
+
|
6
|
+
# The class used by a Website to do the logging and the normal output.
|
7
|
+
class Logger
|
8
|
+
|
9
|
+
# Specifies whether log output should be synchronous with normal output.
|
10
|
+
attr_reader :sync
|
11
|
+
|
12
|
+
# Normal output verbosity (:normal, :verbose, :quiet).
|
13
|
+
attr_accessor :verbosity
|
14
|
+
|
15
|
+
# Create a new Logger object which uses +outdev+ as output device. If +sync+ is set to +true+,
|
16
|
+
# log messages are interspersed with normal output.
|
17
|
+
def initialize(outdev=$stdout, sync=false)
|
18
|
+
@sync = sync
|
19
|
+
@outdev = outdev
|
20
|
+
@logger = (@sync ? ::Logger.new(@outdev) : ::Logger.new(@logio = StringIO.new))
|
21
|
+
@logger.formatter = Proc.new do |severity, timestamp, progname, msg|
|
22
|
+
if self.level == ::Logger::DEBUG
|
23
|
+
"%5s -- %s: %s\n" % [severity, progname, msg ]
|
24
|
+
else
|
25
|
+
"%5s -- %s\n" % [severity, msg]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
self.level = ::Logger::WARN
|
29
|
+
self.verbosity = :normal
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the output of the logger when #sync is +false+. Otherwise an empty string is returned.
|
33
|
+
def log_output
|
34
|
+
@sync ? '' : @logio.string
|
35
|
+
end
|
36
|
+
|
37
|
+
# The severity threshold level.
|
38
|
+
def level
|
39
|
+
@logger.level
|
40
|
+
end
|
41
|
+
|
42
|
+
# Set the severity threshold to +value+ which can be one of the stdlib Logger severity levels.
|
43
|
+
def level=(value)
|
44
|
+
@logger.level = value
|
45
|
+
end
|
46
|
+
|
47
|
+
# Log a message of +sev_level+ from +source+. The mandatory block has to return the message.
|
48
|
+
def log(sev_level, source='', &block)
|
49
|
+
if sev_level == :stdout
|
50
|
+
@outdev.write(block.call + "\n") if @verbosity == :normal || @verbosity == :verbose
|
51
|
+
elsif sev_level == :verbose
|
52
|
+
@outdev.write(block.call + "\n") if @verbosity == :verbose
|
53
|
+
else
|
54
|
+
@logger.send(sev_level, source, &block)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Utiltity method for logging an error message.
|
59
|
+
def error(source='', &block); log(:error, source, &block); end
|
60
|
+
|
61
|
+
# Utiltity method for logging a warning message.
|
62
|
+
def warn(source='', &block); log(:warn, source, &block); end
|
63
|
+
|
64
|
+
# Utiltity method for logging an informational message.
|
65
|
+
def info(source='', &block); log(:info, source, &block); end
|
66
|
+
|
67
|
+
# Utiltity method for logging a debug message.
|
68
|
+
def debug(source='', &block); log(:debug, source, &block); end
|
69
|
+
|
70
|
+
# Utiltity method for writing a normal output message.
|
71
|
+
def stdout(source='', &block); log(:stdout, source, &block); end
|
72
|
+
|
73
|
+
# Utiltity method for writing a verbose output message.
|
74
|
+
def verbose(source='', &block); log(:verbose, source, &block); end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
data/lib/webgen/node.rb
ADDED
@@ -0,0 +1,347 @@
|
|
1
|
+
require 'webgen/websiteaccess'
|
2
|
+
require 'webgen/loggable'
|
3
|
+
require 'webgen/path'
|
4
|
+
require 'uri'
|
5
|
+
require 'set'
|
6
|
+
require 'pathname'
|
7
|
+
|
8
|
+
module Webgen
|
9
|
+
|
10
|
+
# Represents a file, a directory or a fragment. A node always belongs to a Tree.
|
11
|
+
class Node
|
12
|
+
|
13
|
+
include WebsiteAccess
|
14
|
+
include Loggable
|
15
|
+
|
16
|
+
# The parent node.
|
17
|
+
attr_reader :parent
|
18
|
+
|
19
|
+
# The children of this node.
|
20
|
+
attr_reader :children
|
21
|
+
|
22
|
+
# The full output path of this node.
|
23
|
+
attr_reader :path
|
24
|
+
|
25
|
+
# The tree to which this node belongs.
|
26
|
+
attr_reader :tree
|
27
|
+
|
28
|
+
# The canonical name of this node.
|
29
|
+
attr_reader :cn
|
30
|
+
|
31
|
+
# The absolute canonical name of this node.
|
32
|
+
attr_reader :absolute_cn
|
33
|
+
|
34
|
+
# The localized canonical name of this node.
|
35
|
+
attr_reader :lcn
|
36
|
+
|
37
|
+
# The absolute localized canonical name of this node.
|
38
|
+
attr_reader :absolute_lcn
|
39
|
+
|
40
|
+
# The level of the node. The level specifies how deep the node is in the hierarchy.
|
41
|
+
attr_reader :level
|
42
|
+
|
43
|
+
# The language of this node.
|
44
|
+
attr_reader :lang
|
45
|
+
|
46
|
+
# Meta information associated with the node.
|
47
|
+
attr_reader :meta_info
|
48
|
+
|
49
|
+
# Set by other objects to +true+ if they think the object has changed since the last run. Must
|
50
|
+
# not be set to +false+ once it is +true+!
|
51
|
+
attr_accessor :dirty
|
52
|
+
|
53
|
+
# Set by other objects to +true+ if the meta information of the node has changed since the last
|
54
|
+
# run. Must not be set to +false+ once it is +true+!
|
55
|
+
attr_accessor :dirty_meta_info
|
56
|
+
|
57
|
+
# Has the node been created or has it been read from the cache?
|
58
|
+
attr_accessor :created
|
59
|
+
|
60
|
+
# Create a new Node instance.
|
61
|
+
#
|
62
|
+
# +parent+ (immutable)::
|
63
|
+
# The parent node under which this nodes should be created.
|
64
|
+
# +path+ (immutable)::
|
65
|
+
# The full output path for this node. If this node is a directory, the path must have a
|
66
|
+
# trailing slash (<tt>dir/</tt>). If it is a fragment, the hash sign must be the first
|
67
|
+
# character of the path (<tt>#fragment</tt>). This can also be an absolute path like
|
68
|
+
# <tt>http://myhost.com/</tt>.
|
69
|
+
# +cn+ (immutable)::
|
70
|
+
# The canonical name for this node. Needs to be of the form <tt>basename.ext</tt> or
|
71
|
+
# <tt>basename</tt> where +basename+ does not contain any dots. Also, the +basename+ must not
|
72
|
+
# include a language part!
|
73
|
+
# +meta_info+::
|
74
|
+
# A hash with meta information for the new node.
|
75
|
+
#
|
76
|
+
# The language of a node is taken from the meta information +lang+ and the entry is deleted from
|
77
|
+
# the meta information hash. The language cannot be changed afterwards! If no +lang+ key is
|
78
|
+
# found, the node is language neutral.
|
79
|
+
def initialize(parent, path, cn, meta_info = {})
|
80
|
+
@parent = parent
|
81
|
+
@path = path.freeze
|
82
|
+
@cn = cn.chomp('/').freeze
|
83
|
+
@lang = meta_info.delete('lang').freeze
|
84
|
+
@lang = nil unless is_file?
|
85
|
+
@meta_info = meta_info
|
86
|
+
@children = []
|
87
|
+
@dirty = true
|
88
|
+
@created = true
|
89
|
+
init_rest
|
90
|
+
end
|
91
|
+
|
92
|
+
# Return the meta information item for +key+.
|
93
|
+
def [](key)
|
94
|
+
@meta_info[key]
|
95
|
+
end
|
96
|
+
|
97
|
+
# Assign +value+ to the meta information item for +key+.
|
98
|
+
def []=(key, value)
|
99
|
+
@meta_info[key] = value
|
100
|
+
end
|
101
|
+
|
102
|
+
# Return the node information hash which contains information for processing the node.
|
103
|
+
def node_info
|
104
|
+
tree.node_info[@absolute_lcn] ||= {}
|
105
|
+
end
|
106
|
+
|
107
|
+
# Check if the node is a directory.
|
108
|
+
def is_directory?; @path[-1] == ?/; end
|
109
|
+
|
110
|
+
# Check if the node is a file.
|
111
|
+
def is_file?; !is_directory? && !is_fragment?; end
|
112
|
+
|
113
|
+
# Check if the node is a fragment.
|
114
|
+
def is_fragment?; @cn[0] == ?# end
|
115
|
+
|
116
|
+
# Check if the node is the root node.
|
117
|
+
def is_root?; self == tree.root; end
|
118
|
+
|
119
|
+
# Return +true+ if the node has changed since the last webgen run. If it has changed, +dirty+ is
|
120
|
+
# set to +true+.
|
121
|
+
def changed?
|
122
|
+
if_not_checked(:node) do
|
123
|
+
@dirty = @dirty || meta_info_changed?
|
124
|
+
@dirty = node_info[:used_nodes].any? {|n| n != @absolute_lcn && (!tree[n] || tree[n].changed?)} unless @dirty
|
125
|
+
website.blackboard.dispatch_msg(:node_changed?, self) unless @dirty
|
126
|
+
end
|
127
|
+
@dirty
|
128
|
+
end
|
129
|
+
|
130
|
+
# Return +true+ if the meta information of the node has changed.
|
131
|
+
def meta_info_changed?
|
132
|
+
if_not_checked(:meta_info) do
|
133
|
+
@dirty_meta_info = node_info[:used_meta_info_nodes].any? do |n|
|
134
|
+
n != @absolute_lcn && (!tree[n] || tree[n].meta_info_changed?)
|
135
|
+
end unless @dirty_meta_info
|
136
|
+
website.blackboard.dispatch_msg(:node_meta_info_changed?, self) unless @dirty_meta_info
|
137
|
+
end
|
138
|
+
@dirty_meta_info
|
139
|
+
end
|
140
|
+
|
141
|
+
# Return an informative representation of the node.
|
142
|
+
def inspect
|
143
|
+
"<##{self.class.name}: alcn=#{@absolute_lcn}>"
|
144
|
+
end
|
145
|
+
|
146
|
+
# Return +true+ if the alcn matches the pattern. See File.fnmatch for useable patterns.
|
147
|
+
def =~(pattern)
|
148
|
+
File.fnmatch(pattern, @absolute_lcn, File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Sort nodes by using the meta info +sort_info+ (or +title+ if +sort_info+ is not set) of both
|
152
|
+
# involved nodes.
|
153
|
+
def <=>(other)
|
154
|
+
self_so = (@meta_info['sort_info'] && @meta_info['sort_info'].to_s) || @meta_info['title'] || ''
|
155
|
+
other_so = (other['sort_info'] && other['sort_info'].to_s) || other['title'] || ''
|
156
|
+
if self_so !~ /\D/ && other_so !~ /\D/
|
157
|
+
self_so = self_so.to_i
|
158
|
+
other_so = other_so.to_i
|
159
|
+
end
|
160
|
+
self_so <=> other_so
|
161
|
+
end
|
162
|
+
|
163
|
+
# Construct the absolute (localized) canonical name by using the +parent+ node and +name+ (which
|
164
|
+
# can be a cn or an lcn). The +type+ can be either +:alcn+ or +:acn+.
|
165
|
+
def self.absolute_name(parent, name, type)
|
166
|
+
if parent.kind_of?(Tree)
|
167
|
+
''
|
168
|
+
else
|
169
|
+
parent = parent.parent while parent.is_fragment? # Handle fragment nodes specially in case they are nested
|
170
|
+
parent_name = (type == :alcn ? parent.absolute_lcn : parent.absolute_cn)
|
171
|
+
parent_name + (parent_name !~ /\/$/ && (parent.is_directory? || parent == parent.tree.dummy_root) ? '/' : '') + name
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Construct an internal URL for the given +name+ which can be a acn/alcn/path.
|
176
|
+
def self.url(name)
|
177
|
+
url = URI::parse(name)
|
178
|
+
url = URI::parse('webgen://webgen.localhost/') + url unless url.absolute?
|
179
|
+
url
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
# Check if the this node is in the subtree which is spanned by +node+. The check is performed
|
184
|
+
# using only the +parent+ information of the involved nodes, NOT the actual path/alcn values!
|
185
|
+
def in_subtree_of?(node)
|
186
|
+
temp = self
|
187
|
+
temp = temp.parent while temp != tree.dummy_root && temp != node
|
188
|
+
temp != tree.dummy_root
|
189
|
+
end
|
190
|
+
|
191
|
+
# Return the node with the same canonical name but in language +lang+ or, if no such node
|
192
|
+
# exists, an unlocalized version of the node. If no such node is found either, +nil+ is
|
193
|
+
# returned.
|
194
|
+
def in_lang(lang)
|
195
|
+
avail = @tree.node_access[:acn][@absolute_cn]
|
196
|
+
avail.find do |n|
|
197
|
+
n = n.parent while n.is_fragment?
|
198
|
+
n.lang == lang
|
199
|
+
end || avail.find do |n|
|
200
|
+
n = n.parent while n.is_fragment?
|
201
|
+
n.lang.nil?
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# Return the node representing the given +path+ which can be an acn/alcn. The path can be
|
206
|
+
# absolute (i.e. starting with a slash) or relative to the current node. If no node exists for
|
207
|
+
# the given path or if the path is invalid, +nil+ is returned.
|
208
|
+
#
|
209
|
+
# If the +path+ is an alcn and a node is found, it is returned. If the +path+ is an acn, the
|
210
|
+
# correct localized node according to +lang+ is returned or if no such node exists but an
|
211
|
+
# unlocalized version does, the unlocalized node is returned.
|
212
|
+
def resolve(path, lang = nil)
|
213
|
+
url = self.class.url(self.is_directory? ? File.join(@absolute_lcn, '/') : @absolute_lcn) + path
|
214
|
+
|
215
|
+
path = url.path + (url.fragment.nil? ? '' : '#' + url.fragment)
|
216
|
+
path.chomp!('/') unless path == '/'
|
217
|
+
return nil if path =~ /^\/\.\./
|
218
|
+
|
219
|
+
node = @tree[path, :alcn]
|
220
|
+
if node && node.absolute_cn != path
|
221
|
+
node
|
222
|
+
else
|
223
|
+
(node = @tree[path, :acn]) && node.in_lang(lang)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# Return the relative path to the given path +other+. The parameter +other+ can be a Node or a
|
228
|
+
# String.
|
229
|
+
def route_to(other)
|
230
|
+
my_url = self.class.url(@path)
|
231
|
+
other_url = if other.kind_of?(Node)
|
232
|
+
self.class.url(other.routing_node(@lang).path)
|
233
|
+
elsif other.kind_of?(String)
|
234
|
+
my_url + other
|
235
|
+
else
|
236
|
+
raise ArgumentError, "improper class for argument"
|
237
|
+
end
|
238
|
+
|
239
|
+
# resolve any '.' and '..' paths in the target url
|
240
|
+
if other_url.path =~ /\/\.\.?\// && other_url.scheme == 'webgen'
|
241
|
+
other_url.path = Pathname.new(other_url.path).cleanpath.to_s
|
242
|
+
end
|
243
|
+
route = my_url.route_to(other_url).to_s
|
244
|
+
(route == '' ? File.basename(self.path) : route)
|
245
|
+
end
|
246
|
+
|
247
|
+
# Return the routing node in language +lang+ which is the node that is used when routing to this
|
248
|
+
# node. The returned node can differ from the node itself in case of a directory where the
|
249
|
+
# routing node is the directory index node.
|
250
|
+
def routing_node(lang)
|
251
|
+
if !is_directory?
|
252
|
+
self
|
253
|
+
else
|
254
|
+
key = [absolute_lcn, :index_node, lang]
|
255
|
+
vcache = website.cache.volatile
|
256
|
+
return vcache[key] if vcache.has_key?(key)
|
257
|
+
|
258
|
+
index_path = self.meta_info['index_path']
|
259
|
+
if index_path.nil?
|
260
|
+
vcache[key] = self
|
261
|
+
else
|
262
|
+
index_node = resolve(index_path, lang)
|
263
|
+
if index_node
|
264
|
+
vcache[key] = index_node
|
265
|
+
log(:info) { "Directory index path for <#{absolute_lcn}> => <#{index_node.absolute_lcn}>" }
|
266
|
+
else
|
267
|
+
vcache[key] = self
|
268
|
+
log(:warn) { "No directory index path found for directory <#{absolute_lcn}>" }
|
269
|
+
end
|
270
|
+
end
|
271
|
+
vcache[key]
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
# Return a HTML link from this node to the +node+ or, if this node and +node+ are the same and
|
276
|
+
# the parameter <tt>website.link_to_current_page</tt> is +false+, a +span+ element with the link
|
277
|
+
# text.
|
278
|
+
#
|
279
|
+
# You can optionally specify additional attributes for the HTML element in the +attr+ Hash.
|
280
|
+
# Also, the meta information +link_attrs+ of the given +node+ is used, if available, to set
|
281
|
+
# attributes. However, the +attr+ parameter takes precedence over the +link_attrs+ meta
|
282
|
+
# information. Be aware that all key-value pairs with Symbol keys are removed before the
|
283
|
+
# attributes are written. Therefore you always need to specify general attributes with Strings!
|
284
|
+
#
|
285
|
+
# If the special value <tt>:link_text</tt> is present in the attributes, it will be used as the
|
286
|
+
# link text; otherwise the title of the +node+ will be used.
|
287
|
+
#
|
288
|
+
# If the special value <tt>:lang</tt> is present in the attributes, it will be used as parameter
|
289
|
+
# to the <tt>node.routing_node</tt> call for getting the linked-to node instead of this node's
|
290
|
+
# +lang+ attribute. Note: this is only useful when linking to a directory.
|
291
|
+
def link_to(node, attr = {})
|
292
|
+
attr = node['link_attrs'].merge(attr) if node['link_attrs'].kind_of?(Hash)
|
293
|
+
rnode = node.routing_node(attr[:lang] || @lang)
|
294
|
+
link_text = attr[:link_text] || (rnode != node && rnode['routed_title']) || node['title']
|
295
|
+
attr.delete_if {|k,v| k.kind_of?(Symbol)}
|
296
|
+
|
297
|
+
use_link = (rnode != self || website.config['website.link_to_current_page'])
|
298
|
+
attr['href'] = self.route_to(rnode) if use_link
|
299
|
+
attrs = attr.collect {|name,value| "#{name.to_s}=\"#{value}\"" }.sort.unshift('').join(' ')
|
300
|
+
(use_link ? "<a#{attrs}>#{link_text}</a>" : "<span#{attrs}>#{link_text}</span>")
|
301
|
+
end
|
302
|
+
|
303
|
+
#######
|
304
|
+
private
|
305
|
+
#######
|
306
|
+
|
307
|
+
# Do the rest of the initialization.
|
308
|
+
def init_rest
|
309
|
+
@lcn = Path.lcn(@cn, @lang)
|
310
|
+
@absolute_cn = self.class.absolute_name(@parent, @cn, :acn)
|
311
|
+
@absolute_lcn = self.class.absolute_name(@parent, @lcn, :alcn)
|
312
|
+
|
313
|
+
@level = -1
|
314
|
+
@tree = @parent
|
315
|
+
(@level += 1; @tree = @tree.parent) while !@tree.kind_of?(Tree)
|
316
|
+
|
317
|
+
@tree.register_node(self)
|
318
|
+
@parent.children << self unless @parent == @tree
|
319
|
+
|
320
|
+
self.node_info[:used_nodes] = Set.new
|
321
|
+
self.node_info[:used_meta_info_nodes] = Set.new
|
322
|
+
end
|
323
|
+
|
324
|
+
# Only run the code in the block if this node has not already been checked. Different checks are
|
325
|
+
# supported by setting a different +type+ value.
|
326
|
+
def if_not_checked(type)
|
327
|
+
array = (website.cache.volatile[:node_change_checking] ||= {})[type] ||= []
|
328
|
+
if !array.include?(self)
|
329
|
+
array << self
|
330
|
+
yield
|
331
|
+
array.delete(self)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
# Delegate missing methods to a processor. The current node is placed into the argument array as
|
336
|
+
# the first argument before the method +name+ is invoked on the processor.
|
337
|
+
def method_missing(name, *args, &block)
|
338
|
+
if node_info[:processor]
|
339
|
+
website.cache.instance(node_info[:processor]).send(name, *([self] + args), &block)
|
340
|
+
else
|
341
|
+
super
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
end
|
346
|
+
|
347
|
+
end
|