gettalong-webgen 0.5.7.20090227 → 0.5.8.20090507
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/Rakefile +37 -36
- data/data/webgen/resources.yaml +2 -2
- data/data/webgen/webgui/app.rb +11 -0
- data/data/webgen/webgui/controller/main.rb +30 -26
- data/data/webgen/webgui/{view/page.xhtml → layout/default.xhtml} +8 -8
- data/data/webgen/webgui/start.rb +9 -0
- data/data/webgen/webgui/view/create_website.xhtml +6 -14
- data/data/webgen/webgui/view/manage_website.xhtml +2 -2
- data/data/webgen/website_bundles/default/README +6 -0
- data/data/webgen/website_bundles/default/src/index.page +15 -0
- data/data/webgen/{website_styles → website_bundles/style}/1024px/README +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/1024px/src/default.css +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/1024px/src/default.template +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/1024px/src/images/background.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas00/README +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas00/src/default.css +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas00/src/default.template +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas00/src/images/bg.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas00/src/images/front.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas00/src/images/menubg.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas00/src/images/menubg2.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas01/README +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas01/src/default.css +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas01/src/default.template +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas01/src/images/bg.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas01/src/images/front.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas01/src/print.css +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas03/README +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas03/src/default.css +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas03/src/default.template +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas03/src/images/bodybg.png +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas03/src/images/contbg.png +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas03/src/images/footerbg.png +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas03/src/images/gradient1.png +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas03/src/images/gradient2.png +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas04/README +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/default.css +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/default.template +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/blinkarrow.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/bodybg.png +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/contentbg.png +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/entrybg.png +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/flash.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/flash2.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/globe.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/globebottom.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/linkarrow.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/menuhover.png +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas05/README +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas05/src/default.css +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas05/src/default.template +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas05/src/images/bodybg.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas05/src/images/front.png +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas06/README +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/default.css +6 -4
- data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/default.template +2 -2
- data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/images/bodybg.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/images/boxbg.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/images/greypx.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/images/header.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/images/innerbg.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/images/leaves.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/images/tabs.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas07/README +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas07/src/browserfix.css +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas07/src/default.css +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas07/src/default.template +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas07/src/images/bodybg.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas07/src/images/sidebarbg.gif +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas08/README +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas08/src/default.css +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas08/src/default.template +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/README +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/default.css +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/default.template +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/bodybg-black.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/bodybg-green.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/bodybg-orange.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/bodybg-purple.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/bodybg-red.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/bodybg.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/footerbg.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/menuhover-black.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/menuhover-green.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/menuhover-orange.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/menuhover-purple.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/menuhover-red.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/menuhover.jpg +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/simple/README +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/simple/src/default.css +0 -0
- data/data/webgen/{website_styles → website_bundles/style}/simple/src/default.template +0 -0
- data/data/webgen/website_skeleton/README +1 -1
- data/data/webgen/website_skeleton/config.yaml +5 -4
- data/doc/contentprocessor/blocks.page +43 -10
- data/doc/contentprocessor/builder.page +1 -1
- data/doc/contentprocessor/erb.page +12 -11
- data/doc/contentprocessor/redcloth.page +3 -1
- data/doc/extensions.page +3 -3
- data/doc/faq.page +13 -10
- data/doc/getting_started.page +12 -15
- data/doc/index.page +7 -1
- data/doc/manual.page +78 -27
- data/doc/reference_configuration.page +166 -3
- data/doc/reference_website_styles.page +28 -0
- data/doc/source/filesystem.page +39 -0
- data/doc/source/tararchive.page +40 -0
- data/doc/tag/tikz.page +2 -1
- data/doc/webgen_page_format.page +13 -12
- data/doc/website_styles.metainfo +8 -0
- data/lib/webgen/blackboard.rb +2 -2
- data/lib/webgen/cache.rb +4 -4
- data/lib/webgen/cli.rb +29 -16
- data/lib/webgen/cli/apply_command.rb +66 -0
- data/lib/webgen/cli/create_command.rb +22 -16
- data/lib/webgen/cli/utils.rb +23 -0
- data/lib/webgen/cli/webgui_command.rb +31 -16
- data/lib/webgen/configuration.rb +8 -6
- data/lib/webgen/contentprocessor.rb +4 -5
- data/lib/webgen/contentprocessor/blocks.rb +2 -0
- data/lib/webgen/contentprocessor/builder.rb +6 -3
- data/lib/webgen/contentprocessor/erb.rb +6 -3
- data/lib/webgen/contentprocessor/erubis.rb +7 -6
- data/lib/webgen/contentprocessor/haml.rb +6 -3
- data/lib/webgen/contentprocessor/rdoc.rb +0 -1
- data/lib/webgen/contentprocessor/redcloth.rb +3 -1
- data/lib/webgen/context.rb +73 -0
- data/lib/webgen/context/nodes.rb +36 -0
- data/lib/webgen/coreext.rb +3 -2
- data/lib/webgen/default_config.rb +3 -1
- data/lib/webgen/deprecated.rb +53 -0
- data/lib/webgen/node.rb +24 -19
- data/lib/webgen/output.rb +50 -7
- data/lib/webgen/page.rb +45 -36
- data/lib/webgen/path.rb +1 -1
- data/lib/webgen/source.rb +32 -4
- data/lib/webgen/source/resource.rb +3 -3
- data/lib/webgen/source/stacked.rb +1 -1
- data/lib/webgen/source/tararchive.rb +73 -0
- data/lib/webgen/sourcehandler.rb +4 -4
- data/lib/webgen/sourcehandler/base.rb +36 -24
- data/lib/webgen/sourcehandler/copy.rb +1 -1
- data/lib/webgen/sourcehandler/feed.rb +2 -2
- data/lib/webgen/sourcehandler/fragment.rb +1 -1
- data/lib/webgen/sourcehandler/metainfo.rb +15 -6
- data/lib/webgen/sourcehandler/page.rb +9 -5
- data/lib/webgen/sourcehandler/virtual.rb +44 -7
- data/lib/webgen/tag/base.rb +19 -13
- data/lib/webgen/tag/link.rb +1 -0
- data/lib/webgen/version.rb +1 -1
- data/lib/webgen/webgentask.rb +15 -13
- data/lib/webgen/website.rb +42 -11
- data/lib/webgen/websiteaccess.rb +1 -1
- data/lib/webgen/websitemanager.rb +61 -66
- data/man/man1/webgen.1 +4 -0
- data/misc/default.css +13 -0
- data/misc/default.template +1 -1
- data/misc/htmldoc.metainfo +2 -1
- data/misc/style.page +33 -0
- data/test/test_cli.rb +1 -7
- data/test/test_common_sitemap.rb +2 -2
- data/test/test_contentprocessor_blocks.rb +14 -1
- data/test/test_contentprocessor_builder.rb +3 -1
- data/test/test_contentprocessor_erb.rb +3 -2
- data/test/test_contentprocessor_erubis.rb +3 -3
- data/test/test_contentprocessor_fragments.rb +3 -3
- data/test/test_contentprocessor_haml.rb +3 -2
- data/test/test_contentprocessor_maruku.rb +3 -3
- data/test/test_contentprocessor_rdiscount.rb +1 -1
- data/test/test_contentprocessor_rdoc.rb +1 -1
- data/test/test_contentprocessor_redcloth.rb +9 -2
- data/test/test_contentprocessor_sass.rb +1 -1
- data/test/test_contentprocessor_tags.rb +1 -1
- data/test/{test_contentprocessor_context.rb → test_context.rb} +9 -7
- data/test/test_node.rb +27 -21
- data/test/test_page.rb +4 -4
- data/test/test_source_tararchive.rb +65 -0
- data/test/test_sourcehandler_fragment.rb +1 -1
- data/test/test_sourcehandler_memory.rb +6 -6
- data/test/test_sourcehandler_metainfo.rb +34 -13
- data/test/test_sourcehandler_page.rb +8 -0
- data/test/test_sourcehandler_virtual.rb +51 -12
- data/test/test_tag_breadcrumbtrail.rb +4 -4
- data/test/test_tag_coderay.rb +1 -1
- data/test/test_tag_date.rb +1 -1
- data/test/test_tag_executecommand.rb +1 -1
- data/test/test_tag_includefile.rb +3 -3
- data/test/test_tag_langbar.rb +6 -6
- data/test/test_tag_link.rb +8 -2
- data/test/test_tag_menu.rb +9 -9
- data/test/test_tag_metainfo.rb +1 -1
- data/test/test_tag_relocatable.rb +1 -1
- data/test/test_tag_sitemap.rb +1 -1
- data/test/test_tag_tikz.rb +2 -2
- data/test/test_website.rb +17 -0
- data/test/test_websitemanager.rb +16 -21
- metadata +181 -171
- data/data/webgen/website_templates/default/README +0 -6
- data/data/webgen/website_templates/default/src/index.page +0 -8
- data/data/webgen/website_templates/project/README +0 -5
- data/data/webgen/website_templates/project/src/about.page +0 -12
- data/data/webgen/website_templates/project/src/download.page +0 -15
- data/data/webgen/website_templates/project/src/features.page +0 -8
- data/data/webgen/website_templates/project/src/index.page +0 -9
- data/data/webgen/website_templates/project/src/screenshots.page +0 -18
- data/lib/webgen/contentprocessor/context.rb +0 -89
data/lib/webgen/node.rb
CHANGED
@@ -10,6 +10,13 @@ require 'pathname'
|
|
10
10
|
module Webgen
|
11
11
|
|
12
12
|
# Represents a file, a directory or a fragment. A node always belongs to a Tree.
|
13
|
+
#
|
14
|
+
# All needed meta and processing information is associated with a Node. The meta information is
|
15
|
+
# available throught the #[] and #meta_info accessors, the processing information through the
|
16
|
+
# #node_info accessor.
|
17
|
+
#
|
18
|
+
# Although node information should be changed by code, it is not advised to change meta
|
19
|
+
# information values in code since this may lead to unwanted behaviour!
|
13
20
|
class Node
|
14
21
|
|
15
22
|
include WebsiteAccess
|
@@ -50,18 +57,18 @@ module Webgen
|
|
50
57
|
|
51
58
|
# Create a new Node instance.
|
52
59
|
#
|
53
|
-
# +parent+ (immutable)
|
60
|
+
# [+parent+ (immutable)]
|
54
61
|
# The parent node under which this nodes should be created.
|
55
|
-
# +path+ (immutable)
|
62
|
+
# [+path+ (immutable)]
|
56
63
|
# The full output path for this node. If this node is a directory, the path must have a
|
57
64
|
# trailing slash (<tt>dir/</tt>). If it is a fragment, the hash sign must be the first
|
58
65
|
# character of the path (<tt>#fragment</tt>). This can also be an absolute path like
|
59
66
|
# <tt>http://myhost.com/</tt>.
|
60
|
-
# +cn+ (immutable)
|
67
|
+
# [+cn+ (immutable)]
|
61
68
|
# The canonical name for this node. Needs to be of the form <tt>basename.ext</tt> or
|
62
69
|
# <tt>basename</tt> where +basename+ does not contain any dots. Also, the +basename+ must not
|
63
70
|
# include a language part!
|
64
|
-
# +meta_info
|
71
|
+
# [+meta_info+]
|
65
72
|
# A hash with meta information for the new node.
|
66
73
|
#
|
67
74
|
# The language of a node is taken from the meta information +lang+ and the entry is deleted from
|
@@ -121,13 +128,13 @@ module Webgen
|
|
121
128
|
|
122
129
|
# Check if the node is flagged with one of the following:
|
123
130
|
#
|
124
|
-
# :created
|
125
|
-
# :reinit
|
126
|
-
# :dirty
|
131
|
+
# [:created] Has the node been created or has it been read from the cache?
|
132
|
+
# [:reinit] Does the node need to be reinitialized?
|
133
|
+
# [:dirty] Set by other objects to +true+ if they think the object has changed since the last
|
127
134
|
# run. Must not be set to +false+ once it is +true+!
|
128
|
-
# :dirty_meta_info
|
135
|
+
# [:dirty_meta_info] Set by other objects to +true+ if the meta information of the node has
|
129
136
|
# changed since the last run. Must not be set to +false+ once it is +true+!
|
130
|
-
def flagged(key)
|
137
|
+
def flagged?(key)
|
131
138
|
@flags.include?(key)
|
132
139
|
end
|
133
140
|
|
@@ -154,10 +161,11 @@ module Webgen
|
|
154
161
|
def changed?
|
155
162
|
if_not_checked(:node) do
|
156
163
|
flag(:dirty) if meta_info_changed? ||
|
157
|
-
node_info[:used_nodes].any? {|n| n != @absolute_lcn && (!tree[n] || tree[n].changed?)}
|
158
|
-
|
164
|
+
node_info[:used_nodes].any? {|n| n != @absolute_lcn && (!tree[n] || tree[n].changed?)} ||
|
165
|
+
node_info[:used_meta_info_nodes].any? {|n| n != @absolute_lcn && (!tree[n] || tree[n].meta_info_changed?)}
|
166
|
+
website.blackboard.dispatch_msg(:node_changed?, self) unless flagged?(:dirty)
|
159
167
|
end
|
160
|
-
flagged(:dirty)
|
168
|
+
flagged?(:dirty)
|
161
169
|
end
|
162
170
|
|
163
171
|
# Return +true+ if the meta information of the node has changed.
|
@@ -168,12 +176,9 @@ module Webgen
|
|
168
176
|
# dirty.
|
169
177
|
def meta_info_changed?
|
170
178
|
if_not_checked(:meta_info) do
|
171
|
-
|
172
|
-
n != @absolute_lcn && (!tree[n] || tree[n].meta_info_changed?)
|
173
|
-
end
|
174
|
-
website.blackboard.dispatch_msg(:node_meta_info_changed?, self) unless flagged(:dirty_meta_info)
|
179
|
+
website.blackboard.dispatch_msg(:node_meta_info_changed?, self) unless flagged?(:dirty_meta_info)
|
175
180
|
end
|
176
|
-
flagged(:dirty_meta_info)
|
181
|
+
flagged?(:dirty_meta_info)
|
177
182
|
end
|
178
183
|
|
179
184
|
# Return an informative representation of the node.
|
@@ -199,7 +204,7 @@ module Webgen
|
|
199
204
|
end
|
200
205
|
|
201
206
|
# Construct the absolute (localized) canonical name by using the +parent+ node and +name+ (which
|
202
|
-
# can be a cn or an lcn). The +type+ can be either
|
207
|
+
# can be a cn or an lcn). The +type+ can be either <tt>:alcn</tt> or <tt>:acn</tt>.
|
203
208
|
def self.absolute_name(parent, name, type)
|
204
209
|
if parent.kind_of?(Tree)
|
205
210
|
''
|
@@ -326,7 +331,7 @@ module Webgen
|
|
326
331
|
#
|
327
332
|
# If the special value <tt>:lang</tt> is present in the attributes, it will be used as parameter
|
328
333
|
# to the <tt>node.routing_node</tt> call for getting the linked-to node instead of this node's
|
329
|
-
# +lang+ attribute. Note
|
334
|
+
# +lang+ attribute. *Note*: this is only useful when linking to a directory.
|
330
335
|
def link_to(node, attr = {})
|
331
336
|
attr = node['link_attrs'].merge(attr) if node['link_attrs'].kind_of?(Hash)
|
332
337
|
rnode = node.routing_node(attr[:lang] || @lang)
|
data/lib/webgen/output.rb
CHANGED
@@ -4,22 +4,65 @@ module Webgen
|
|
4
4
|
|
5
5
|
# Namespace for all classes that know how to write out node content.
|
6
6
|
#
|
7
|
-
#
|
7
|
+
# == Implementing an output class
|
8
8
|
#
|
9
9
|
# Output classes know how to write rendered node data to an output location.
|
10
10
|
#
|
11
11
|
# An output class must respond to three methods
|
12
12
|
#
|
13
|
-
# <tt>exists?(path)</tt
|
13
|
+
# [<tt>exists?(path)</tt>]
|
14
14
|
# Return +true+ if the output path exists.
|
15
|
-
# <tt>delete(path)</tt
|
15
|
+
# [<tt>delete(path)</tt>]
|
16
16
|
# Delete the given output path.
|
17
|
-
# <tt>write(path, data, type)</tt
|
18
|
-
# Write the data to the given output path
|
19
|
-
#
|
20
|
-
# <tt>
|
17
|
+
# [<tt>write(path, data, type)</tt>]
|
18
|
+
# Write the +data+ to the given output +path+. The parameter +data+ is either a String with the
|
19
|
+
# content or a Webgen::Path::SourceIO object. The parameter +type+ specifies the type of the to
|
20
|
+
# be written path: <tt>:file</tt> or <tt>:directory</tt>.
|
21
|
+
# [<tt>read(path)</tt>]
|
21
22
|
# Return the content of the given path if it exists or raise an error otherwise.
|
22
23
|
#
|
24
|
+
# It seems a bit odd that an output instance has to implement reading functionality. However,
|
25
|
+
# consider the case where you want webgen to render a website programmatically and *use* the
|
26
|
+
# output. In this case you need a way to get to content of the written files! This functionality
|
27
|
+
# is used, for example, in the webgui.
|
28
|
+
#
|
29
|
+
# == Sample Output Class
|
30
|
+
#
|
31
|
+
# Following is a simple but actually used (by the webgui) output class which stores the written
|
32
|
+
# nodes in a hash in memory:
|
33
|
+
#
|
34
|
+
# class MemoryOutput
|
35
|
+
# include Webgen::WebsiteAccess
|
36
|
+
#
|
37
|
+
# attr_reader :data
|
38
|
+
#
|
39
|
+
# def initialize
|
40
|
+
# @data = {}
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# def exists?(path)
|
44
|
+
# @data.has_key?(path)
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# def delete(path)
|
48
|
+
# @data.delete(path)
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# def write(path, io, type = :file)
|
52
|
+
# @data[path] = [(io.kind_of?(String) ? io : io.data), type]
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# def read(path)
|
56
|
+
# path = File.join('/', path)
|
57
|
+
# raise "No such file #{path}" unless @data[path] && @data[path].last == :file
|
58
|
+
# @data[path].first
|
59
|
+
# end
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# WebsiteAccess.website.config.output(['MemoryOutput'])
|
63
|
+
#
|
64
|
+
# The last line is used to tell webgen to use this new output class instead of the default one.
|
65
|
+
#
|
23
66
|
module Output
|
24
67
|
|
25
68
|
autoload :FileSystem, 'webgen/output/filesystem'
|
data/lib/webgen/page.rb
CHANGED
@@ -4,52 +4,61 @@ require 'yaml'
|
|
4
4
|
|
5
5
|
module Webgen
|
6
6
|
|
7
|
-
# A
|
8
|
-
class
|
7
|
+
# A Page object wraps a meta information hash and an array of Block objects. It is normally
|
8
|
+
# generated from a file or string in Webgen Page Format using the provided class methods.
|
9
|
+
class Page
|
9
10
|
|
10
|
-
# The
|
11
|
-
|
11
|
+
# A single block within a Page object. The content of the block can be rendered using the #render method.
|
12
|
+
class Block
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
# The name of the block.
|
15
|
+
attr_reader :name
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
# The content of the block.
|
18
|
+
attr_reader :content
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
@name, @content, @options = name, content, options
|
22
|
-
end
|
20
|
+
# The options set specifically for this block.
|
21
|
+
attr_reader :options
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
# Returns the given context with the rendered content.
|
28
|
-
def render(context)
|
29
|
-
context[:content] = @content.dup
|
30
|
-
context[:block] = self
|
31
|
-
@options['pipeline'].to_s.split(/,/).each do |processor|
|
32
|
-
raise "No such content processor available: #{processor}" unless context[:processors].has_key?(processor)
|
33
|
-
context[:processors][processor].call(context)
|
23
|
+
# Create a new block with the name +name+ and the given +content+ and +options+.
|
24
|
+
def initialize(name, content, options)
|
25
|
+
@name, @content, @options = name, content, options
|
34
26
|
end
|
35
|
-
context
|
36
|
-
end
|
37
27
|
|
38
|
-
|
28
|
+
# Render the block using the provided context object.
|
29
|
+
#
|
30
|
+
# The context object needs to respond to <tt>#[]</tt> and <tt>#[]=</tt> (e.g. a Hash is a valid
|
31
|
+
# context object) and the key <tt>:processors</tt> needs to contain a Hash which maps processor
|
32
|
+
# names to processor objects that respond to <tt>#call</tt>.
|
33
|
+
#
|
34
|
+
# Uses the content processors specified in the +pipeline+ key of the +options+ attribute to do
|
35
|
+
# the actual rendering.
|
36
|
+
#
|
37
|
+
# Returns the given context with the rendered content.
|
38
|
+
def render(context)
|
39
|
+
context[:content] = @content.dup
|
40
|
+
context[:block] = self
|
41
|
+
@options['pipeline'].to_s.split(/,/).each do |processor|
|
42
|
+
raise "No such content processor available: #{processor}" unless context[:processors].has_key?(processor)
|
43
|
+
context[:processors][processor].call(context)
|
44
|
+
end
|
45
|
+
context
|
46
|
+
end
|
39
47
|
|
48
|
+
end
|
40
49
|
|
41
|
-
# Raised during parsing of data in Webgen Page Format if the data is invalid.
|
42
|
-
class WebgenPageFormatError < RuntimeError; end
|
43
50
|
|
44
|
-
|
45
|
-
|
46
|
-
|
51
|
+
# Raised during parsing of data in Webgen Page Format if the data is invalid.
|
52
|
+
class FormatError < RuntimeError; end
|
53
|
+
|
47
54
|
|
55
|
+
# :stopdoc:
|
48
56
|
RE_META_INFO_START = /\A---\s*(?:\n|\r|\r\n)/m
|
49
57
|
RE_META_INFO = /\A---\s*(?:\n|\r|\r\n).*?(?:\n|\r|\r\n)(?=---.*?(?:\n|\r|\r\n)|\Z)/m
|
50
58
|
RE_BLOCKS_OPTIONS = /^--- *?(?: *((?:\w+:[^\s]* *)*))?$|^$/
|
51
59
|
RE_BLOCKS_START = /^--- .*?$|^--- *$/
|
52
60
|
RE_BLOCKS = /(?:(#{RE_BLOCKS_START})|\A)(.*?)(?:(?=#{RE_BLOCKS_START})|\Z)/m
|
61
|
+
# :startdoc:
|
53
62
|
|
54
63
|
class << self
|
55
64
|
|
@@ -81,17 +90,17 @@ module Webgen
|
|
81
90
|
# original +data+ is used for checking the validness of the meta information block.
|
82
91
|
def parse_meta_info(mi_data, data)
|
83
92
|
if mi_data.nil? && data =~ RE_META_INFO_START
|
84
|
-
raise
|
93
|
+
raise FormatError, 'Found start line for meta information block but no valid meta information block'
|
85
94
|
elsif mi_data.nil?
|
86
95
|
{}
|
87
96
|
else
|
88
97
|
begin
|
89
98
|
meta_info = YAML::load(mi_data.to_s)
|
90
99
|
unless meta_info.kind_of?(Hash)
|
91
|
-
raise
|
100
|
+
raise FormatError, "Invalid structure of meta information block: expected YAML hash but found #{meta_info.class}"
|
92
101
|
end
|
93
102
|
rescue ArgumentError => e
|
94
|
-
raise
|
103
|
+
raise FormatError, e.message
|
95
104
|
end
|
96
105
|
meta_info
|
97
106
|
end
|
@@ -101,20 +110,20 @@ module Webgen
|
|
101
110
|
# which is used for setting the block names and options.
|
102
111
|
def parse_blocks(data, meta_info)
|
103
112
|
scanned = data.scan(RE_BLOCKS)
|
104
|
-
raise(
|
113
|
+
raise(FormatError, 'No content blocks specified') if scanned.length == 0
|
105
114
|
|
106
115
|
blocks = {}
|
107
116
|
scanned.each_with_index do |block_data, index|
|
108
117
|
options, content = *block_data
|
109
118
|
md = RE_BLOCKS_OPTIONS.match(options.to_s)
|
110
|
-
raise(
|
119
|
+
raise(FormatError, "Found invalid blocks starting line for block #{index+1}: #{options}") if content =~ /\A---/ || md.nil?
|
111
120
|
options = Hash[*md[1].to_s.scan(/(\w+):([^\s]*)/).map {|k,v| [k, (v == '' ? nil : YAML::load(v))]}.flatten]
|
112
121
|
options = (meta_info['blocks']['default'] || {} rescue {}).
|
113
122
|
merge((meta_info['blocks'][index+1] || {} rescue {})).
|
114
123
|
merge(options)
|
115
124
|
|
116
125
|
name = options.delete('name') || (index == 0 ? 'content' : 'block' + (index + 1).to_s)
|
117
|
-
raise(
|
126
|
+
raise(FormatError, "Previously used name '#{name}' also used for block #{index+1}") if blocks.has_key?(name)
|
118
127
|
content ||= ''
|
119
128
|
content.gsub!(/^(\\+)(---.*?)$/) {|m| "\\" * ($1.length / 2) + $2}
|
120
129
|
content.strip!
|
data/lib/webgen/path.rb
CHANGED
data/lib/webgen/source.rb
CHANGED
@@ -4,15 +4,42 @@ module Webgen
|
|
4
4
|
|
5
5
|
# Namespace for all classes that provide source paths.
|
6
6
|
#
|
7
|
-
#
|
7
|
+
# == Implementing a source class
|
8
8
|
#
|
9
9
|
# Source classes provide access to the source paths on which the source handlers act.
|
10
10
|
#
|
11
11
|
# A source class only needs to respond to the method +paths+ which needs to return a set of paths
|
12
12
|
# for the source. The returned paths must respond to the method <tt>changed?</tt> (has to return
|
13
|
-
# +true+ if the paths has changed since the last webgen run)
|
14
|
-
#
|
15
|
-
# on each path object.
|
13
|
+
# +true+ if the paths has changed since the last webgen run). The default implementation in the
|
14
|
+
# Path class just returns +true+. One can either derive a specialized path class or define
|
15
|
+
# singleton methods on each path object.
|
16
|
+
#
|
17
|
+
# == Sample Source Class
|
18
|
+
#
|
19
|
+
# Following is a simple source class which has stored the paths and their contents in a hash:
|
20
|
+
#
|
21
|
+
# require 'stringio'
|
22
|
+
#
|
23
|
+
# class MemorySource
|
24
|
+
#
|
25
|
+
# CONTENT = {
|
26
|
+
# '/directory/' => nil,
|
27
|
+
# '/directory/file.page' => "This is the content of the file"
|
28
|
+
# }
|
29
|
+
#
|
30
|
+
# def paths
|
31
|
+
# CONTENT.collect do |path, content|
|
32
|
+
# Webgen::Path.new(path) { StringIO.new(content.to_s) }
|
33
|
+
# end.to_set
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# You can use this source class in your website (after placing the code in, for example,
|
39
|
+
# <tt>ext/init.rb</tt>) by updating the <tt>sources</tt> configuration option (the following code
|
40
|
+
# has to be placed after the definition of the +MemorySource+ class):
|
41
|
+
#
|
42
|
+
# WebsiteAccess.website.config['sources'] << ['/', MemorySource]
|
16
43
|
#
|
17
44
|
module Source
|
18
45
|
|
@@ -20,6 +47,7 @@ module Webgen
|
|
20
47
|
autoload :FileSystem, 'webgen/source/filesystem'
|
21
48
|
autoload :Stacked, 'webgen/source/stacked'
|
22
49
|
autoload :Resource, 'webgen/source/resource'
|
50
|
+
autoload :TarArchive, 'webgen/source/tararchive'
|
23
51
|
|
24
52
|
end
|
25
53
|
|
@@ -5,15 +5,15 @@ require 'webgen/source'
|
|
5
5
|
|
6
6
|
module Webgen::Source
|
7
7
|
|
8
|
-
# This class is used to provide access to
|
8
|
+
# This class is used to provide access to sources provided by resources.
|
9
9
|
class Resource
|
10
10
|
|
11
11
|
include Webgen::WebsiteAccess
|
12
12
|
|
13
|
-
# The glob specifying the resources.
|
13
|
+
# The glob (see File.fnmatch) specifying the resources.
|
14
14
|
attr_reader :glob
|
15
15
|
|
16
|
-
# The glob specifying the paths that should be used from the resources.
|
16
|
+
# The glob (see File.fnmatch) specifying the paths that should be used from the resources.
|
17
17
|
attr_reader :paths_glob
|
18
18
|
|
19
19
|
# The prefix that should optionally be stripped from the paths.
|
@@ -9,7 +9,7 @@ module Webgen::Source
|
|
9
9
|
# * First, it can be used to access more than one source. This is useful when your website
|
10
10
|
# consists of more than one source directory and you want to use all of them.
|
11
11
|
#
|
12
|
-
# * Second, sources can mounted on specific directories. For example, a folder with images that
|
12
|
+
# * Second, sources can be mounted on specific directories. For example, a folder with images that
|
13
13
|
# you don't want to copy to the website source directory can be mounted under <tt>/images</tt>
|
14
14
|
# sothat they are available nonetheless.
|
15
15
|
#
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require 'webgen/websiteaccess'
|
5
|
+
require 'webgen/path'
|
6
|
+
require 'open-uri'
|
7
|
+
require 'zlib'
|
8
|
+
require 'archive/tar/minitar'
|
9
|
+
|
10
|
+
module Webgen
|
11
|
+
|
12
|
+
# This class is used to read source paths from a (gzipped) tar archive. The archive can be remote
|
13
|
+
# (http(s) or ftp) or local.
|
14
|
+
#
|
15
|
+
# For example, the following are all valid URIs:
|
16
|
+
# http://example.com/directory/file.tgz
|
17
|
+
# /home/test/my.tar.gz
|
18
|
+
# ftp://ftp.example.com/archives/archive.tar
|
19
|
+
#
|
20
|
+
class Source::TarArchive
|
21
|
+
|
22
|
+
# A special Webgen::Path class for handling paths from a tar archive.
|
23
|
+
class Path < Webgen::Path
|
24
|
+
|
25
|
+
# Create a new tar archive path object for the entry +entry+.
|
26
|
+
def initialize(path, data, mtime, uri)
|
27
|
+
super(path) { StringIO.new(data.to_s) }
|
28
|
+
@uri = uri
|
29
|
+
@mtime = mtime
|
30
|
+
WebsiteAccess.website.cache[[:tararchive_path, @uri, path]] = @mtime if WebsiteAccess.website
|
31
|
+
@meta_info['modified_at'] = @mtime
|
32
|
+
end
|
33
|
+
|
34
|
+
# Return +true+ if the tar archive path used by the object has been modified.
|
35
|
+
def changed?
|
36
|
+
!WebsiteAccess.website || @mtime > WebsiteAccess.website.cache[[:tararchive_path, @uri, path]]
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
# The URI of the tar archive.
|
42
|
+
attr_reader :uri
|
43
|
+
|
44
|
+
# The glob (see File.fnmatch for details) that is used to specify which paths in the archive should
|
45
|
+
# be returned by #paths.
|
46
|
+
attr_reader :glob
|
47
|
+
|
48
|
+
# Create a new tar archive source for the URI string +uri+.
|
49
|
+
def initialize(uri, glob = '**/*')
|
50
|
+
@uri = uri
|
51
|
+
@glob = glob
|
52
|
+
end
|
53
|
+
|
54
|
+
# Return all paths in the tar archive available at #uri.
|
55
|
+
def paths
|
56
|
+
if !defined?(@paths)
|
57
|
+
stream = open(@uri)
|
58
|
+
stream = Zlib::GzipReader.new(stream) if @uri =~ /(\.tar\.gz|\.tgz)$/
|
59
|
+
Archive::Tar::Minitar::Input.open(stream) do |input|
|
60
|
+
@paths = input.collect do |entry|
|
61
|
+
path = entry.full_name
|
62
|
+
next unless File.fnmatch(@glob, path, File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
|
63
|
+
path += '/' if entry.directory? && path[-1] != ?/
|
64
|
+
Path.new(path, entry.read, Time.at(entry.mtime), @uri)
|
65
|
+
end.compact.to_set
|
66
|
+
end
|
67
|
+
end
|
68
|
+
@paths
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|