webgen 0.5.8 → 0.5.9
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/COPYING +4 -0
- data/ChangeLog +1037 -0
- data/Rakefile +5 -6
- data/THANKS +1 -0
- data/VERSION +1 -1
- data/bin/webgen +1 -1
- data/data/webgen/passive_sources/images/generated_by_webgen.png +0 -0
- data/data/webgen/passive_sources/images/webgen_logo.png +0 -0
- data/data/webgen/passive_sources/stylesheets/coderay-default.css +129 -0
- data/data/webgen/passive_sources/templates/atom_feed.template +38 -0
- data/data/webgen/passive_sources/templates/rss_feed.template +28 -0
- data/data/webgen/passive_sources/templates/sitemap.template +21 -0
- data/data/webgen/resources.yaml +2 -1
- data/data/webgen/website_skeleton/Rakefile +5 -1
- data/doc/contentprocessor/builder.page +2 -2
- data/doc/contentprocessor/erb.page +5 -2
- data/doc/contentprocessor/erubis.page +2 -2
- data/doc/contentprocessor/head.page +21 -0
- data/doc/contentprocessor/tidy.page +14 -0
- data/doc/extensions.page +1 -1
- data/doc/faq.page +2 -2
- data/doc/manual.page +108 -43
- data/doc/reference_configuration.page +83 -5
- data/doc/reference_metainfo.page +24 -4
- data/doc/reference_website_styles.page +2 -2
- data/doc/sourcehandler/feed.page +11 -13
- data/doc/sourcehandler/metainfo.page +10 -3
- data/doc/sourcehandler/page.page +4 -4
- data/doc/sourcehandler/sitemap.page +8 -7
- data/doc/tag/coderay.page +6 -2
- data/doc/tag/includefile.page +1 -1
- data/doc/tag/menu.page +3 -0
- data/lib/webgen/cli/apply_command.rb +1 -1
- data/lib/webgen/cli/utils.rb +2 -2
- data/lib/webgen/common.rb +0 -9
- data/lib/webgen/contentprocessor.rb +18 -3
- data/lib/webgen/contentprocessor/blocks.rb +67 -36
- data/lib/webgen/contentprocessor/builder.rb +5 -2
- data/lib/webgen/contentprocessor/erb.rb +4 -2
- data/lib/webgen/contentprocessor/erubis.rb +5 -2
- data/lib/webgen/contentprocessor/haml.rb +6 -2
- data/lib/webgen/contentprocessor/head.rb +64 -0
- data/lib/webgen/contentprocessor/maruku.rb +3 -1
- data/lib/webgen/contentprocessor/rdiscount.rb +2 -0
- data/lib/webgen/contentprocessor/rdoc.rb +2 -0
- data/lib/webgen/contentprocessor/redcloth.rb +2 -0
- data/lib/webgen/contentprocessor/sass.rb +5 -3
- data/lib/webgen/contentprocessor/tags.rb +40 -24
- data/lib/webgen/contentprocessor/tidy.rb +38 -0
- data/lib/webgen/context.rb +13 -4
- data/lib/webgen/context/render.rb +32 -0
- data/lib/webgen/context/tags.rb +20 -0
- data/lib/webgen/default_config.rb +15 -4
- data/lib/webgen/deprecated.rb +38 -4
- data/lib/webgen/error.rb +135 -0
- data/lib/webgen/node.rb +48 -40
- data/lib/webgen/output.rb +5 -3
- data/lib/webgen/output/filesystem.rb +4 -4
- data/lib/webgen/page.rb +4 -4
- data/lib/webgen/path.rb +161 -58
- data/lib/webgen/source.rb +9 -6
- data/lib/webgen/source/filesystem.rb +1 -1
- data/lib/webgen/source/stacked.rb +13 -5
- data/lib/webgen/source/tararchive.rb +6 -2
- data/lib/webgen/sourcehandler.rb +100 -54
- data/lib/webgen/sourcehandler/base.rb +58 -24
- data/lib/webgen/sourcehandler/copy.rb +6 -5
- data/lib/webgen/sourcehandler/directory.rb +3 -9
- data/lib/webgen/sourcehandler/feed.rb +25 -50
- data/lib/webgen/sourcehandler/fragment.rb +10 -8
- data/lib/webgen/sourcehandler/memory.rb +9 -10
- data/lib/webgen/sourcehandler/metainfo.rb +9 -9
- data/lib/webgen/sourcehandler/page.rb +6 -5
- data/lib/webgen/sourcehandler/sitemap.rb +22 -22
- data/lib/webgen/sourcehandler/template.rb +6 -6
- data/lib/webgen/sourcehandler/virtual.rb +19 -17
- data/lib/webgen/tag/base.rb +27 -27
- data/lib/webgen/tag/breadcrumbtrail.rb +3 -3
- data/lib/webgen/tag/coderay.rb +19 -8
- data/lib/webgen/tag/executecommand.rb +4 -3
- data/lib/webgen/tag/langbar.rb +2 -2
- data/lib/webgen/tag/link.rb +8 -7
- data/lib/webgen/tag/menu.rb +2 -2
- data/lib/webgen/tag/metainfo.rb +1 -1
- data/lib/webgen/tag/relocatable.rb +17 -21
- data/lib/webgen/tag/tikz.rb +7 -10
- data/lib/webgen/tree.rb +7 -7
- data/lib/webgen/version.rb +1 -1
- data/lib/webgen/website.rb +32 -2
- data/misc/default.css +8 -2
- data/misc/default.template +2 -2
- data/misc/logo.svg +313 -0
- data/misc/style.page +1 -1
- data/test/helper.rb +18 -2
- data/test/test_cli.rb +104 -0
- data/test/test_common_sitemap.rb +1 -1
- data/test/test_contentprocessor.rb +8 -2
- data/test/test_contentprocessor_blocks.rb +17 -8
- data/test/test_contentprocessor_builder.rb +13 -2
- data/test/test_contentprocessor_erb.rb +9 -3
- data/test/test_contentprocessor_erubis.rb +9 -3
- data/test/test_contentprocessor_fragments.rb +12 -11
- data/test/test_contentprocessor_haml.rb +11 -2
- data/test/test_contentprocessor_head.rb +44 -0
- data/test/test_contentprocessor_maruku.rb +5 -1
- data/test/test_contentprocessor_rdiscount.rb +4 -0
- data/test/test_contentprocessor_rdoc.rb +4 -0
- data/test/test_contentprocessor_redcloth.rb +5 -1
- data/test/test_contentprocessor_sass.rb +8 -2
- data/test/test_contentprocessor_tags.rb +22 -7
- data/test/test_contentprocessor_tidy.rb +34 -0
- data/test/test_context.rb +39 -0
- data/test/test_error.rb +85 -0
- data/test/test_node.rb +57 -21
- data/test/test_page.rb +23 -5
- data/test/test_path.rb +120 -64
- data/test/test_source_filesystem.rb +1 -1
- data/test/test_source_stacked.rb +19 -6
- data/test/test_sourcehandler_base.rb +63 -50
- data/test/test_sourcehandler_copy.rb +6 -6
- data/test/test_sourcehandler_directory.rb +8 -12
- data/test/test_sourcehandler_feed.rb +15 -7
- data/test/test_sourcehandler_fragment.rb +6 -5
- data/test/test_sourcehandler_main.rb +39 -0
- data/test/test_sourcehandler_memory.rb +4 -4
- data/test/test_sourcehandler_metainfo.rb +20 -11
- data/test/test_sourcehandler_page.rb +10 -10
- data/test/test_sourcehandler_sitemap.rb +24 -5
- data/test/test_sourcehandler_template.rb +18 -15
- data/test/test_sourcehandler_virtual.rb +9 -5
- data/test/test_tag_base.rb +6 -29
- data/test/test_tag_coderay.rb +16 -3
- data/test/test_tag_executecommand.rb +2 -2
- data/test/test_tag_link.rb +5 -4
- data/test/test_tag_menu.rb +15 -15
- data/test/test_tag_metainfo.rb +1 -0
- data/test/test_tag_relocatable.rb +3 -2
- data/test/test_tag_tikz.rb +5 -5
- data/test/test_tree.rb +8 -8
- data/test/test_website.rb +15 -0
- metadata +21 -14
- data/test/test_common.rb +0 -18
data/lib/webgen/context.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
2
|
require 'webgen/context/nodes'
|
|
3
|
+
require 'webgen/context/tags'
|
|
4
|
+
require 'webgen/context/render'
|
|
3
5
|
|
|
4
6
|
module Webgen
|
|
5
7
|
|
|
@@ -13,17 +15,23 @@ module Webgen
|
|
|
13
15
|
# The content string that should be processed.
|
|
14
16
|
#
|
|
15
17
|
# [<tt>:processors</tt>]
|
|
16
|
-
# Normally an AccessHash object providing access to all available content
|
|
18
|
+
# Normally an ContentProcessor::AccessHash object providing access to all available content
|
|
19
|
+
# processors.
|
|
17
20
|
#
|
|
18
21
|
# [<tt>:chain</tt>]
|
|
19
22
|
# The chain of nodes that is processed. There are some utiltity methods for getting
|
|
20
23
|
# special nodes of the chain (see #ref_node, #content_node and #dest_node).
|
|
24
|
+
#
|
|
25
|
+
# The +persistent+ options hash is shared by all cloned Context objects.
|
|
21
26
|
class Context
|
|
22
27
|
|
|
23
28
|
include Webgen::WebsiteAccess
|
|
24
29
|
public :website
|
|
25
30
|
|
|
26
|
-
#
|
|
31
|
+
# The persistent options. Once initialized, all cloned objects refer to the same hash.
|
|
32
|
+
attr_reader :persistent
|
|
33
|
+
|
|
34
|
+
# Processing options.
|
|
27
35
|
attr_accessor :options
|
|
28
36
|
|
|
29
37
|
# Create a new Context object. You can use the +options+ hash to set needed options.
|
|
@@ -35,17 +43,18 @@ module Webgen
|
|
|
35
43
|
#
|
|
36
44
|
# [<tt>:processors</tt>]
|
|
37
45
|
# Is set to a new AccessHash.
|
|
38
|
-
def initialize(options = {})
|
|
46
|
+
def initialize(options = {}, persistent = {})
|
|
39
47
|
@options = {
|
|
40
48
|
:content => '',
|
|
41
49
|
:processors => Webgen::ContentProcessor::AccessHash.new
|
|
42
50
|
}.merge(options)
|
|
51
|
+
@persistent = persistent
|
|
43
52
|
end
|
|
44
53
|
|
|
45
54
|
# Create a copy of the current object. You can use the +options+ parameter to override options
|
|
46
55
|
# of the current Context object in the newly created Context object.
|
|
47
56
|
def clone(options = {})
|
|
48
|
-
self.class.new(@options.merge(options))
|
|
57
|
+
self.class.new(@options.merge(options), @persistent)
|
|
49
58
|
end
|
|
50
59
|
|
|
51
60
|
# Return the value of the option +name+.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Webgen
|
|
2
|
+
|
|
3
|
+
class Context
|
|
4
|
+
|
|
5
|
+
# Render the named block and return the result.
|
|
6
|
+
#
|
|
7
|
+
# call-seq:
|
|
8
|
+
# context.render_block(block_name)<br />
|
|
9
|
+
# context.render_block(:name => block_name, :option => value, ...)
|
|
10
|
+
#
|
|
11
|
+
# This method uses the functionality of the content processor +blocks+ for doing the actual
|
|
12
|
+
# work, so you may also want to look at Webgen::ContentProcessor::Blocks#render_block. You can
|
|
13
|
+
# call this method in two ways:
|
|
14
|
+
#
|
|
15
|
+
# [<tt>#render_block(block_name)</tt>]
|
|
16
|
+
# Renders the block named +block_name+ of the next node in the current node chain. This is the
|
|
17
|
+
# version that most want to use since it is equivalent to the use of <tt><webgen:block
|
|
18
|
+
# name="block_name" /></tt>. It is equivalent to <tt>#render_block(:name =>
|
|
19
|
+
# block_name)</tt>.
|
|
20
|
+
#
|
|
21
|
+
# [<tt>#render_block(opts_hash)</tt>]
|
|
22
|
+
# This version allows the same level of control over the output as the blocks content
|
|
23
|
+
# processor. For a list of valid options have a look at the documentation of the
|
|
24
|
+
# Webgen::ContentProcessor::Blocks#render_block method!
|
|
25
|
+
def render_block(name_or_hash)
|
|
26
|
+
name_or_hash = {:name => name_or_hash} if name_or_hash.kind_of?(String)
|
|
27
|
+
website.cache.instance('Webgen::ContentProcessor::Blocks').render_block(self, name_or_hash)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Webgen
|
|
2
|
+
|
|
3
|
+
class Context
|
|
4
|
+
|
|
5
|
+
# Returns the result of evaluating the webgen tag +name+ with the tag parameters +params+ and
|
|
6
|
+
# the +body+ in the current context.
|
|
7
|
+
#
|
|
8
|
+
# Have a look at Webgen::Tag::Base for more information about webgen tags!
|
|
9
|
+
#
|
|
10
|
+
# This method is useful when you want to have the functionality of webgen tags available but you
|
|
11
|
+
# don't want to use the content processor for them. Or, for example, if the used markup language
|
|
12
|
+
# uses a similar markup as webgen tags do and therefore you can't use the normal webgen tags
|
|
13
|
+
# content processor.
|
|
14
|
+
def tag(name, params = {}, body = '')
|
|
15
|
+
website.cache.instance('Webgen::ContentProcessor::Tags').process_tag(name, params, body, self)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
@@ -43,6 +43,7 @@ end
|
|
|
43
43
|
|
|
44
44
|
# All things regarding sources
|
|
45
45
|
config.sources [['/', "Webgen::Source::FileSystem", 'src']], :doc => 'One or more sources from which files are read, relative to website directory'
|
|
46
|
+
config.passive_sources([['/', "Webgen::Source::Resource", "webgen-passive-sources"]], :doc => 'One or more sources for delayed node creation on node resolution')
|
|
46
47
|
|
|
47
48
|
# All things regarding source handler
|
|
48
49
|
config.sourcehandler.patterns({
|
|
@@ -70,7 +71,7 @@ config.sourcehandler.default_lang_in_output_path(false, :doc => 'Specifies wheth
|
|
|
70
71
|
config.sourcehandler.default_meta_info({
|
|
71
72
|
:all => {
|
|
72
73
|
'output_path' => 'standard',
|
|
73
|
-
'output_path_style' => [:parent, :
|
|
74
|
+
'output_path_style' => [:parent, :basename, ['.', :lang], :ext]
|
|
74
75
|
},
|
|
75
76
|
'Webgen::SourceHandler::Copy' => {
|
|
76
77
|
'kind' => 'asset'
|
|
@@ -88,19 +89,21 @@ config.sourcehandler.default_meta_info({
|
|
|
88
89
|
'kind' => 'fragment'
|
|
89
90
|
},
|
|
90
91
|
'Webgen::SourceHandler::Template' => {
|
|
91
|
-
'blocks' => {'default' => {'pipeline' => 'erb,tags,blocks'}}
|
|
92
|
+
'blocks' => {'default' => {'pipeline' => 'erb,tags,blocks,head'}}
|
|
92
93
|
},
|
|
93
94
|
'Webgen::SourceHandler::Metainfo' => {
|
|
94
95
|
'blocks' => {1 => {'name' => 'paths'}, 2 => {'name' => 'alcn'}}
|
|
95
96
|
},
|
|
96
97
|
'Webgen::SourceHandler::Feed' => {
|
|
97
98
|
'rss' => true,
|
|
98
|
-
'atom' => true
|
|
99
|
+
'atom' => true,
|
|
100
|
+
'blocks' => {'default' => {'pipeline' => 'erb'}}
|
|
99
101
|
},
|
|
100
102
|
'Webgen::SourceHandler::Sitemap' => {
|
|
101
103
|
'default_priority' => 0.5,
|
|
102
104
|
'default_change_freq' => 'weekly',
|
|
103
|
-
'common.sitemap.any_lang' => true
|
|
105
|
+
'common.sitemap.any_lang' => true,
|
|
106
|
+
'blocks' => {'default' => {'pipeline' => 'erb'}}
|
|
104
107
|
}
|
|
105
108
|
}, :doc => "Default meta information for all nodes and for nodes belonging to a specific source handler")
|
|
106
109
|
|
|
@@ -114,6 +117,8 @@ website.autoload_service(:parse_html_headers, 'Webgen::SourceHandler::Fragment')
|
|
|
114
117
|
|
|
115
118
|
# All things regarding output
|
|
116
119
|
config.output ["Webgen::Output::FileSystem", 'out'], :doc => 'The class which is used to output the generated paths.'
|
|
120
|
+
config.output.do_deletion(false, :doc => 'Specifies whether the generated output paths should be deleted once the sources are deleted')
|
|
121
|
+
|
|
117
122
|
|
|
118
123
|
Webgen::WebsiteAccess.website.blackboard.add_service(:output_instance, Webgen::Output.method(:instance))
|
|
119
124
|
|
|
@@ -134,10 +139,13 @@ config.contentprocessor.map({
|
|
|
134
139
|
'erubis' => 'Webgen::ContentProcessor::Erubis',
|
|
135
140
|
'rdiscount' => 'Webgen::ContentProcessor::RDiscount',
|
|
136
141
|
'fragments' => 'Webgen::ContentProcessor::Fragments',
|
|
142
|
+
'head' => 'Webgen::ContentProcessor::Head',
|
|
143
|
+
'tidy' => 'Webgen::ContentProcessor::Tidy'
|
|
137
144
|
}, :doc => 'Content processor name to class map')
|
|
138
145
|
|
|
139
146
|
Webgen::WebsiteAccess.website.blackboard.add_service(:content_processor_names, Webgen::ContentProcessor.method(:list))
|
|
140
147
|
Webgen::WebsiteAccess.website.blackboard.add_service(:content_processor, Webgen::ContentProcessor.method(:for_name))
|
|
148
|
+
Webgen::WebsiteAccess.website.blackboard.add_service(:content_processor_binary?, Webgen::ContentProcessor.method(:is_binary?))
|
|
141
149
|
|
|
142
150
|
# All things regarding tags
|
|
143
151
|
config.contentprocessor.tags.prefix('', :doc => 'The prefix used for tag names to avoid name clashes when another content processor uses similar markup.')
|
|
@@ -161,6 +169,8 @@ config.contentprocessor.erubis.options({}, :doc => 'A hash of additional options
|
|
|
161
169
|
|
|
162
170
|
config.contentprocessor.redcloth.hard_breaks(false, :doc => 'Specifies whether new lines are turned into hard breaks')
|
|
163
171
|
|
|
172
|
+
config.contentprocessor.tidy.options("-raw", :doc => "The options passed to the tidy command")
|
|
173
|
+
|
|
164
174
|
config.tag.relocatable.path(nil, :doc => 'The path which should be made relocatable', :mandatory => 'default')
|
|
165
175
|
|
|
166
176
|
config.tag.menu.start_level(1, :doc => 'The level at which the menu starts.')
|
|
@@ -196,6 +206,7 @@ config.tag.coderay.line_numbers(true, :doc => 'Show line numbers')
|
|
|
196
206
|
config.tag.coderay.line_number_start(1, :doc => 'Line number of first line')
|
|
197
207
|
config.tag.coderay.bold_every(10, :doc => 'The interval at which the line number appears bold')
|
|
198
208
|
config.tag.coderay.tab_width(8, :doc => 'Number of spaces used for a tabulator')
|
|
209
|
+
config.tag.coderay.css(:style, :doc => 'Specifies how the highlighted code should be styled')
|
|
199
210
|
|
|
200
211
|
config.tag.date.format('%Y-%m-%d %H:%M:%S', :doc => 'The format of the date (same options as Ruby\'s Time#strftime)')
|
|
201
212
|
|
data/lib/webgen/deprecated.rb
CHANGED
|
@@ -3,18 +3,42 @@ module Webgen
|
|
|
3
3
|
class Node
|
|
4
4
|
|
|
5
5
|
def flagged(key)
|
|
6
|
-
warn("Deprecation warning: this method will be removed in one of the next releases - use Node#flagged? instead!")
|
|
6
|
+
warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Node#flagged? instead!")
|
|
7
7
|
flagged?(key)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
+
def absolute_cn
|
|
11
|
+
warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Node#acn instead!")
|
|
12
|
+
acn
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def absolute_lcn
|
|
16
|
+
warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Node#alcn instead!")
|
|
17
|
+
alcn
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class Path
|
|
23
|
+
|
|
24
|
+
def cnbase
|
|
25
|
+
warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Path#basename instead!")
|
|
26
|
+
@basename
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def cnbase=(value)
|
|
30
|
+
warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Path#basename= instead!")
|
|
31
|
+
basename = value
|
|
32
|
+
end
|
|
33
|
+
|
|
10
34
|
end
|
|
11
35
|
|
|
12
36
|
def self.const_missing(const)
|
|
13
37
|
if const.to_s == 'Block'
|
|
14
|
-
warn("Deprecation warning: Webgen::Block name will be removed in one of the next releases - use Webgen::Page::Block instead!")
|
|
38
|
+
warn("Deprecation warning (~ #{caller.first}): Webgen::Block name will be removed in one of the next releases - use Webgen::Page::Block instead!")
|
|
15
39
|
Webgen::Page::Block
|
|
16
40
|
elsif const.to_s == "WebgenPageFormatError"
|
|
17
|
-
warn("Deprecation warning: Webgen::WebgenPageFormatError name will be removed in one of the next releases - use Webgen::Page::FormatError instead!")
|
|
41
|
+
warn("Deprecation warning (~ #{caller.first}): Webgen::WebgenPageFormatError name will be removed in one of the next releases - use Webgen::Page::FormatError instead!")
|
|
18
42
|
Webgen::Page::FormatError
|
|
19
43
|
else
|
|
20
44
|
super
|
|
@@ -25,7 +49,7 @@ module Webgen
|
|
|
25
49
|
|
|
26
50
|
def self.const_missing(const)
|
|
27
51
|
if const.to_s == 'Context'
|
|
28
|
-
warn("Deprecation warning: Webgen::ContentProcessor::Context is now named Webgen::Context! This alias will be removed in one of the next releases.")
|
|
52
|
+
warn("Deprecation warning (~ #{caller.first}): Webgen::ContentProcessor::Context is now named Webgen::Context! This alias will be removed in one of the next releases.")
|
|
29
53
|
Webgen::Context
|
|
30
54
|
else
|
|
31
55
|
super
|
|
@@ -39,6 +63,7 @@ module Webgen
|
|
|
39
63
|
klass.instance_methods.select {|m| m.to_s !~ /^(__|instance_eval|object_id)/}.each {|m| klass.__send__(:undef_method, m)}
|
|
40
64
|
result = klass.new
|
|
41
65
|
result.instance_eval { @old, @new, @obj = old, new, obj }
|
|
66
|
+
def result.inspect; end
|
|
42
67
|
def result.method_missing(sym, *args, &block)
|
|
43
68
|
Kernel::warn("Deprecation warning (~ #{caller.first}): The alias '#{@old}' will be removed in one of the next releases - use '#{@new}' instead!")
|
|
44
69
|
@obj.send(sym, *args, &block)
|
|
@@ -50,4 +75,13 @@ module Webgen
|
|
|
50
75
|
|
|
51
76
|
end
|
|
52
77
|
|
|
78
|
+
module Common
|
|
79
|
+
|
|
80
|
+
def self.absolute_path(path, base)
|
|
81
|
+
warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Webgen::Path.make_absolute(base, path) instead!")
|
|
82
|
+
Path.make_absolute(base, path)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
end
|
|
86
|
+
|
|
53
87
|
end
|
data/lib/webgen/error.rb
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
module Webgen
|
|
4
|
+
|
|
5
|
+
# Custom webgen error.
|
|
6
|
+
class Error < StandardError
|
|
7
|
+
|
|
8
|
+
# The name of the class where the error happened.
|
|
9
|
+
attr_reader :class_name
|
|
10
|
+
|
|
11
|
+
# This is either the source path or the node alcn which is responsible for the error.
|
|
12
|
+
attr_accessor :alcn
|
|
13
|
+
|
|
14
|
+
# The plain error message.
|
|
15
|
+
attr_reader :plain_message
|
|
16
|
+
|
|
17
|
+
# Create a new Error using the provided values.
|
|
18
|
+
#
|
|
19
|
+
# If +msg_or_error+ is a String, it is treated as the error message. If it is an exception, the
|
|
20
|
+
# exception is wrapped.
|
|
21
|
+
def initialize(msg_or_error, class_name = nil, alcn = nil)
|
|
22
|
+
if msg_or_error.kind_of?(String)
|
|
23
|
+
super(msg_or_error)
|
|
24
|
+
@plain_message = msg_or_error
|
|
25
|
+
else
|
|
26
|
+
super(msg_or_error.message)
|
|
27
|
+
set_backtrace(msg_or_error.backtrace)
|
|
28
|
+
@plain_message = msg_or_error.message
|
|
29
|
+
end
|
|
30
|
+
@class_name, @alcn = class_name, alcn
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def message # :nodoc:
|
|
34
|
+
msg = 'Error while working'
|
|
35
|
+
msg += (@alcn ? " on <#{@alcn}>" : '')
|
|
36
|
+
msg += " with #{@class_name}" if @class_name
|
|
37
|
+
msg + ":\n " + plain_message
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# This error is raised when an error condition occurs during the creation of a node.
|
|
43
|
+
class NodeCreationError < Error
|
|
44
|
+
|
|
45
|
+
def message # :nodoc:
|
|
46
|
+
msg = 'Error while creating a node'
|
|
47
|
+
msg += (@alcn ? " from <#{@alcn}>" : '')
|
|
48
|
+
msg += " with #{@class_name}" if @class_name
|
|
49
|
+
msg + ":\n " + plain_message
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# This error is raised when an error condition occurs during rendering of a node.
|
|
56
|
+
class RenderError < Error
|
|
57
|
+
|
|
58
|
+
# The alcn of the file where the error happened. This can be different from #alcn (e.g. a page
|
|
59
|
+
# file is rendered but the error happens in a used template).
|
|
60
|
+
attr_accessor :error_alcn
|
|
61
|
+
|
|
62
|
+
# The line number in the +error_alcn+ where the errror happened.
|
|
63
|
+
attr_accessor :line
|
|
64
|
+
|
|
65
|
+
# Create a new RenderError using the provided values.
|
|
66
|
+
#
|
|
67
|
+
# If +msg_or_error+ is a String, it is treated as the error message. If it is an exception, the
|
|
68
|
+
# exception is wrapped.
|
|
69
|
+
def initialize(msg_or_error, class_name = nil, alcn = nil, error_alcn = nil, line = nil)
|
|
70
|
+
super(msg_or_error, class_name, alcn)
|
|
71
|
+
@error_alcn, @line = error_alcn, line
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def message # :nodoc:
|
|
75
|
+
msg = 'Error '
|
|
76
|
+
if @error_alcn
|
|
77
|
+
msg += "in <#{@error_alcn}"
|
|
78
|
+
msg += ":~#{@line}" if @line
|
|
79
|
+
msg += "> "
|
|
80
|
+
end
|
|
81
|
+
msg += 'while rendering '
|
|
82
|
+
msg += (@alcn ? "<#{@alcn}>" : 'the website')
|
|
83
|
+
msg += " with #{@class_name}" if @class_name
|
|
84
|
+
msg + ":\n " + plain_message
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
# This error is raised when a needed library is not found.
|
|
91
|
+
class LoadError < Error
|
|
92
|
+
|
|
93
|
+
# The name of the library that is missing.
|
|
94
|
+
attr_reader :library
|
|
95
|
+
|
|
96
|
+
# The name of the Rubygem that provides the missing library.
|
|
97
|
+
attr_reader :gem
|
|
98
|
+
|
|
99
|
+
# Create a new LoadError using the provided values.
|
|
100
|
+
#
|
|
101
|
+
# If +library_or_error+ is a String, it is treated as the missing library name and an approriate
|
|
102
|
+
# error message is created. If it is an exception, the exception is wrapped.
|
|
103
|
+
def initialize(library_or_error, class_name = nil, alcn = nil, gem = nil)
|
|
104
|
+
if library_or_error.kind_of?(String)
|
|
105
|
+
msg = "The needed library '#{library_or_error}' is missing."
|
|
106
|
+
msg += " You can install it via rubygems with 'gem install #{gem}'!" if gem
|
|
107
|
+
super(msg, class_name, alcn)
|
|
108
|
+
@library = library_or_error
|
|
109
|
+
else
|
|
110
|
+
super(library_or_error, class_name, alcn)
|
|
111
|
+
@library = nil
|
|
112
|
+
end
|
|
113
|
+
@gem = gem
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# This error is raised when a needed external command is not found.
|
|
120
|
+
class CommandNotFoundError < Error
|
|
121
|
+
|
|
122
|
+
# The command that is missing.
|
|
123
|
+
attr_reader :cmd
|
|
124
|
+
|
|
125
|
+
# Create a new CommandNotFoundError using the provided values.
|
|
126
|
+
#
|
|
127
|
+
# The parameter +cmd+ specifies the command that is missing.
|
|
128
|
+
def initialize(cmd, class_name = nil, alcn = nil)
|
|
129
|
+
super("The needed command '#{cmd}' is missing!", class_name, alcn)
|
|
130
|
+
@cmd = cmd
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
end
|
data/lib/webgen/node.rb
CHANGED
|
@@ -22,10 +22,11 @@ module Webgen
|
|
|
22
22
|
include WebsiteAccess
|
|
23
23
|
include Loggable
|
|
24
24
|
|
|
25
|
-
# The parent node.
|
|
25
|
+
# The parent node. This is in all but one case a Node object. The one exception is that the
|
|
26
|
+
# parent of the Tree#dummy_node is a Tree object.
|
|
26
27
|
attr_reader :parent
|
|
27
28
|
|
|
28
|
-
# The
|
|
29
|
+
# The child nodes of this node.
|
|
29
30
|
attr_reader :children
|
|
30
31
|
|
|
31
32
|
# The full output path of this node.
|
|
@@ -38,13 +39,13 @@ module Webgen
|
|
|
38
39
|
attr_reader :cn
|
|
39
40
|
|
|
40
41
|
# The absolute canonical name of this node.
|
|
41
|
-
attr_reader :
|
|
42
|
+
attr_reader :acn
|
|
42
43
|
|
|
43
44
|
# The localized canonical name of this node.
|
|
44
45
|
attr_reader :lcn
|
|
45
46
|
|
|
46
47
|
# The absolute localized canonical name of this node.
|
|
47
|
-
attr_reader :
|
|
48
|
+
attr_reader :alcn
|
|
48
49
|
|
|
49
50
|
# The level of the node. The level specifies how deep the node is in the hierarchy.
|
|
50
51
|
attr_reader :level
|
|
@@ -76,7 +77,7 @@ module Webgen
|
|
|
76
77
|
# found, the node is language neutral.
|
|
77
78
|
def initialize(parent, path, cn, meta_info = {})
|
|
78
79
|
@parent = parent
|
|
79
|
-
@cn = cn.
|
|
80
|
+
@cn = cn.freeze
|
|
80
81
|
@children = []
|
|
81
82
|
reinit(path, meta_info)
|
|
82
83
|
init_rest
|
|
@@ -111,11 +112,11 @@ module Webgen
|
|
|
111
112
|
|
|
112
113
|
# Return the node information hash which contains information for processing the node.
|
|
113
114
|
def node_info
|
|
114
|
-
tree.node_info[@
|
|
115
|
+
tree.node_info[@alcn] ||= {}
|
|
115
116
|
end
|
|
116
117
|
|
|
117
118
|
# Check if the node is a directory.
|
|
118
|
-
def is_directory?; @path[-1] ==
|
|
119
|
+
def is_directory?; @path[-1] == ?/ && !is_fragment?; end
|
|
119
120
|
|
|
120
121
|
# Check if the node is a file.
|
|
121
122
|
def is_file?; !is_directory? && !is_fragment?; end
|
|
@@ -160,14 +161,23 @@ module Webgen
|
|
|
160
161
|
# thinks it is dirty.
|
|
161
162
|
def changed?
|
|
162
163
|
if_not_checked(:node) do
|
|
163
|
-
flag(:dirty) if meta_info_changed? ||
|
|
164
|
-
node_info[:used_nodes].any? {|n| n != @
|
|
165
|
-
node_info[:used_meta_info_nodes].any? {|n| n != @
|
|
164
|
+
flag(:dirty) if meta_info_changed? || user_nodes_changed? ||
|
|
165
|
+
node_info[:used_nodes].any? {|n| n != @alcn && (!tree[n] || tree[n].changed?)} ||
|
|
166
|
+
node_info[:used_meta_info_nodes].any? {|n| n != @alcn && (!tree[n] || tree[n].meta_info_changed?)}
|
|
166
167
|
website.blackboard.dispatch_msg(:node_changed?, self) unless flagged?(:dirty)
|
|
167
168
|
end
|
|
168
169
|
flagged?(:dirty)
|
|
169
170
|
end
|
|
170
171
|
|
|
172
|
+
# Return +true+ if any node matching a pattern from the meta information +used_nodes+ has changed.
|
|
173
|
+
def user_nodes_changed?
|
|
174
|
+
pattern = [@meta_info['used_nodes']].flatten.compact.collect {|pat| Webgen::Path.make_absolute(parent.alcn, pat)}
|
|
175
|
+
tree.node_access[:alcn].any? do |path, n|
|
|
176
|
+
pattern.any? {|pat| n =~ pat && n.changed?}
|
|
177
|
+
end if pattern.length > 0
|
|
178
|
+
end
|
|
179
|
+
private :user_nodes_changed?
|
|
180
|
+
|
|
171
181
|
# Return +true+ if the meta information of the node has changed.
|
|
172
182
|
#
|
|
173
183
|
# Sends the message <tt>:node_meta_info_changed?</tt> with +self+ as argument unless the meta
|
|
@@ -183,12 +193,12 @@ module Webgen
|
|
|
183
193
|
|
|
184
194
|
# Return an informative representation of the node.
|
|
185
195
|
def inspect
|
|
186
|
-
"<##{self.class.name}: alcn=#{@
|
|
196
|
+
"<##{self.class.name}: alcn=#{@alcn}>"
|
|
187
197
|
end
|
|
188
198
|
|
|
189
199
|
# Return +true+ if the alcn matches the pattern. See File.fnmatch for useable patterns.
|
|
190
200
|
def =~(pattern)
|
|
191
|
-
File.fnmatch(pattern, @
|
|
201
|
+
File.fnmatch(pattern, @alcn, File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
|
|
192
202
|
end
|
|
193
203
|
|
|
194
204
|
# Sort nodes by using the meta info +sort_info+ (or +title+ if +sort_info+ is not set) of both
|
|
@@ -203,22 +213,16 @@ module Webgen
|
|
|
203
213
|
self_so <=> other_so
|
|
204
214
|
end
|
|
205
215
|
|
|
206
|
-
#
|
|
207
|
-
#
|
|
208
|
-
|
|
209
|
-
if parent.kind_of?(Tree)
|
|
210
|
-
''
|
|
211
|
-
else
|
|
212
|
-
parent = parent.parent while parent.is_fragment? # Handle fragment nodes specially in case they are nested
|
|
213
|
-
parent_name = (type == :alcn ? parent.absolute_lcn : parent.absolute_cn)
|
|
214
|
-
parent_name + (parent_name !~ /\/$/ && (parent.is_directory? || parent == parent.tree.dummy_root) ? '/' : '') + name
|
|
215
|
-
end
|
|
216
|
-
end
|
|
216
|
+
# This pattern is the the same as URI::UNSAFE except that the hash character (#) is also
|
|
217
|
+
# not escaped. This is needed sothat paths with fragments work correctly.
|
|
218
|
+
URL_UNSAFE_PATTERN = Regexp.new("[^#{URI::PATTERN::UNRESERVED}#{URI::PATTERN::RESERVED}#]") # :nodoc:
|
|
217
219
|
|
|
218
|
-
# Construct an internal URL for the given +name+ which can be
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
220
|
+
# Construct an internal URL for the given +name+ which can be an acn/alcn/path. If the parameter
|
|
221
|
+
# +make_absolute+ is +true+, then a relative URL will be made absolute by prepending the special
|
|
222
|
+
# URL <tt>webgen:://webgen.localhost/</tt>.
|
|
223
|
+
def self.url(name, make_absolute = true)
|
|
224
|
+
url = URI::parse(URI::escape(name, URL_UNSAFE_PATTERN))
|
|
225
|
+
url = URI::parse('webgen://webgen.localhost/') + url unless url.absolute? || !make_absolute
|
|
222
226
|
url
|
|
223
227
|
end
|
|
224
228
|
|
|
@@ -235,7 +239,7 @@ module Webgen
|
|
|
235
239
|
# exists, an unlocalized version of the node. If no such node is found either, +nil+ is
|
|
236
240
|
# returned.
|
|
237
241
|
def in_lang(lang)
|
|
238
|
-
avail = @tree.node_access[:acn][@
|
|
242
|
+
avail = @tree.node_access[:acn][@acn]
|
|
239
243
|
avail.find do |n|
|
|
240
244
|
n = n.parent while n.is_fragment?
|
|
241
245
|
n.lang == lang
|
|
@@ -252,19 +256,23 @@ module Webgen
|
|
|
252
256
|
# If the +path+ is an alcn and a node is found, it is returned. If the +path+ is an acn, the
|
|
253
257
|
# correct localized node according to +lang+ is returned or if no such node exists but an
|
|
254
258
|
# unlocalized version does, the unlocalized node is returned.
|
|
255
|
-
def resolve(path, lang = nil)
|
|
256
|
-
|
|
259
|
+
def resolve(path, lang = nil, use_passive_sources = true)
|
|
260
|
+
orig_path = path
|
|
261
|
+
url = self.class.url(@alcn) + self.class.url(path, false)
|
|
257
262
|
|
|
258
263
|
path = url.path + (url.fragment.nil? ? '' : '#' + url.fragment)
|
|
259
|
-
path.chomp!('/') unless path == '/'
|
|
260
264
|
return nil if path =~ /^\/\.\./
|
|
261
265
|
|
|
262
266
|
node = @tree[path, :alcn]
|
|
263
|
-
if node
|
|
264
|
-
node
|
|
265
|
-
|
|
266
|
-
|
|
267
|
+
if !node || node.acn == path
|
|
268
|
+
(node = (@tree[path, :acn] || @tree[path + '/', :acn])) && (node = node.in_lang(lang))
|
|
269
|
+
end
|
|
270
|
+
if !node && use_passive_sources && !website.config['passive_sources'].empty?
|
|
271
|
+
nodes = website.blackboard.invoke(:create_nodes_from_paths, [path])
|
|
272
|
+
node = resolve(orig_path, lang, false)
|
|
273
|
+
node.node_info[:used_meta_info_nodes] += nodes.collect {|n| n.alcn} if node
|
|
267
274
|
end
|
|
275
|
+
node
|
|
268
276
|
end
|
|
269
277
|
|
|
270
278
|
# Return the relative path to the given path +other+. The parameter +other+ can be a Node or a
|
|
@@ -295,7 +303,7 @@ module Webgen
|
|
|
295
303
|
if !is_directory?
|
|
296
304
|
self
|
|
297
305
|
else
|
|
298
|
-
key = [
|
|
306
|
+
key = [alcn, :index_node, lang]
|
|
299
307
|
vcache = website.cache.volatile
|
|
300
308
|
return vcache[key] if vcache.has_key?(key)
|
|
301
309
|
|
|
@@ -306,10 +314,10 @@ module Webgen
|
|
|
306
314
|
index_node = resolve(index_path, lang)
|
|
307
315
|
if index_node
|
|
308
316
|
vcache[key] = index_node
|
|
309
|
-
log(:info) { "Directory index path for <#{
|
|
317
|
+
log(:info) { "Directory index path for <#{alcn}> => <#{index_node.alcn}>" }
|
|
310
318
|
elsif log_warning
|
|
311
319
|
vcache[key] = self
|
|
312
|
-
log(:warn) { "No directory index path found for directory <#{
|
|
320
|
+
log(:warn) { "No directory index path found for directory <#{alcn}>" }
|
|
313
321
|
end
|
|
314
322
|
end
|
|
315
323
|
vcache[key] || self
|
|
@@ -351,8 +359,8 @@ module Webgen
|
|
|
351
359
|
# Do the rest of the initialization.
|
|
352
360
|
def init_rest
|
|
353
361
|
@lcn = Path.lcn(@cn, @lang)
|
|
354
|
-
@
|
|
355
|
-
@
|
|
362
|
+
@acn = (@parent.kind_of?(Tree) ? '' : @parent.acn.sub(/#.*$/, '') + @cn)
|
|
363
|
+
@alcn = (@parent.kind_of?(Tree) ? '' : @parent.alcn.sub(/#.*$/, '') + @lcn)
|
|
356
364
|
|
|
357
365
|
@level = -1
|
|
358
366
|
@tree = @parent
|