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.
Files changed (205) hide show
  1. data/Rakefile +37 -36
  2. data/data/webgen/resources.yaml +2 -2
  3. data/data/webgen/webgui/app.rb +11 -0
  4. data/data/webgen/webgui/controller/main.rb +30 -26
  5. data/data/webgen/webgui/{view/page.xhtml → layout/default.xhtml} +8 -8
  6. data/data/webgen/webgui/start.rb +9 -0
  7. data/data/webgen/webgui/view/create_website.xhtml +6 -14
  8. data/data/webgen/webgui/view/manage_website.xhtml +2 -2
  9. data/data/webgen/website_bundles/default/README +6 -0
  10. data/data/webgen/website_bundles/default/src/index.page +15 -0
  11. data/data/webgen/{website_styles → website_bundles/style}/1024px/README +0 -0
  12. data/data/webgen/{website_styles → website_bundles/style}/1024px/src/default.css +0 -0
  13. data/data/webgen/{website_styles → website_bundles/style}/1024px/src/default.template +0 -0
  14. data/data/webgen/{website_styles → website_bundles/style}/1024px/src/images/background.gif +0 -0
  15. data/data/webgen/{website_styles → website_bundles/style}/andreas00/README +0 -0
  16. data/data/webgen/{website_styles → website_bundles/style}/andreas00/src/default.css +0 -0
  17. data/data/webgen/{website_styles → website_bundles/style}/andreas00/src/default.template +0 -0
  18. data/data/webgen/{website_styles → website_bundles/style}/andreas00/src/images/bg.gif +0 -0
  19. data/data/webgen/{website_styles → website_bundles/style}/andreas00/src/images/front.jpg +0 -0
  20. data/data/webgen/{website_styles → website_bundles/style}/andreas00/src/images/menubg.gif +0 -0
  21. data/data/webgen/{website_styles → website_bundles/style}/andreas00/src/images/menubg2.gif +0 -0
  22. data/data/webgen/{website_styles → website_bundles/style}/andreas01/README +0 -0
  23. data/data/webgen/{website_styles → website_bundles/style}/andreas01/src/default.css +0 -0
  24. data/data/webgen/{website_styles → website_bundles/style}/andreas01/src/default.template +0 -0
  25. data/data/webgen/{website_styles → website_bundles/style}/andreas01/src/images/bg.gif +0 -0
  26. data/data/webgen/{website_styles → website_bundles/style}/andreas01/src/images/front.jpg +0 -0
  27. data/data/webgen/{website_styles → website_bundles/style}/andreas01/src/print.css +0 -0
  28. data/data/webgen/{website_styles → website_bundles/style}/andreas03/README +0 -0
  29. data/data/webgen/{website_styles → website_bundles/style}/andreas03/src/default.css +0 -0
  30. data/data/webgen/{website_styles → website_bundles/style}/andreas03/src/default.template +0 -0
  31. data/data/webgen/{website_styles → website_bundles/style}/andreas03/src/images/bodybg.png +0 -0
  32. data/data/webgen/{website_styles → website_bundles/style}/andreas03/src/images/contbg.png +0 -0
  33. data/data/webgen/{website_styles → website_bundles/style}/andreas03/src/images/footerbg.png +0 -0
  34. data/data/webgen/{website_styles → website_bundles/style}/andreas03/src/images/gradient1.png +0 -0
  35. data/data/webgen/{website_styles → website_bundles/style}/andreas03/src/images/gradient2.png +0 -0
  36. data/data/webgen/{website_styles → website_bundles/style}/andreas04/README +0 -0
  37. data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/default.css +0 -0
  38. data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/default.template +0 -0
  39. data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/blinkarrow.gif +0 -0
  40. data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/bodybg.png +0 -0
  41. data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/contentbg.png +0 -0
  42. data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/entrybg.png +0 -0
  43. data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/flash.gif +0 -0
  44. data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/flash2.gif +0 -0
  45. data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/globe.gif +0 -0
  46. data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/globebottom.gif +0 -0
  47. data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/linkarrow.gif +0 -0
  48. data/data/webgen/{website_styles → website_bundles/style}/andreas04/src/images/menuhover.png +0 -0
  49. data/data/webgen/{website_styles → website_bundles/style}/andreas05/README +0 -0
  50. data/data/webgen/{website_styles → website_bundles/style}/andreas05/src/default.css +0 -0
  51. data/data/webgen/{website_styles → website_bundles/style}/andreas05/src/default.template +0 -0
  52. data/data/webgen/{website_styles → website_bundles/style}/andreas05/src/images/bodybg.gif +0 -0
  53. data/data/webgen/{website_styles → website_bundles/style}/andreas05/src/images/front.png +0 -0
  54. data/data/webgen/{website_styles → website_bundles/style}/andreas06/README +0 -0
  55. data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/default.css +6 -4
  56. data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/default.template +2 -2
  57. data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/images/bodybg.gif +0 -0
  58. data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/images/boxbg.gif +0 -0
  59. data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/images/greypx.gif +0 -0
  60. data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/images/header.jpg +0 -0
  61. data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/images/innerbg.gif +0 -0
  62. data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/images/leaves.jpg +0 -0
  63. data/data/webgen/{website_styles → website_bundles/style}/andreas06/src/images/tabs.gif +0 -0
  64. data/data/webgen/{website_styles → website_bundles/style}/andreas07/README +0 -0
  65. data/data/webgen/{website_styles → website_bundles/style}/andreas07/src/browserfix.css +0 -0
  66. data/data/webgen/{website_styles → website_bundles/style}/andreas07/src/default.css +0 -0
  67. data/data/webgen/{website_styles → website_bundles/style}/andreas07/src/default.template +0 -0
  68. data/data/webgen/{website_styles → website_bundles/style}/andreas07/src/images/bodybg.gif +0 -0
  69. data/data/webgen/{website_styles → website_bundles/style}/andreas07/src/images/sidebarbg.gif +0 -0
  70. data/data/webgen/{website_styles → website_bundles/style}/andreas08/README +0 -0
  71. data/data/webgen/{website_styles → website_bundles/style}/andreas08/src/default.css +0 -0
  72. data/data/webgen/{website_styles → website_bundles/style}/andreas08/src/default.template +0 -0
  73. data/data/webgen/{website_styles → website_bundles/style}/andreas09/README +0 -0
  74. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/default.css +0 -0
  75. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/default.template +0 -0
  76. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/bodybg-black.jpg +0 -0
  77. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/bodybg-green.jpg +0 -0
  78. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/bodybg-orange.jpg +0 -0
  79. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/bodybg-purple.jpg +0 -0
  80. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/bodybg-red.jpg +0 -0
  81. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/bodybg.jpg +0 -0
  82. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/footerbg.jpg +0 -0
  83. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/menuhover-black.jpg +0 -0
  84. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/menuhover-green.jpg +0 -0
  85. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/menuhover-orange.jpg +0 -0
  86. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/menuhover-purple.jpg +0 -0
  87. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/menuhover-red.jpg +0 -0
  88. data/data/webgen/{website_styles → website_bundles/style}/andreas09/src/images/menuhover.jpg +0 -0
  89. data/data/webgen/{website_styles → website_bundles/style}/simple/README +0 -0
  90. data/data/webgen/{website_styles → website_bundles/style}/simple/src/default.css +0 -0
  91. data/data/webgen/{website_styles → website_bundles/style}/simple/src/default.template +0 -0
  92. data/data/webgen/website_skeleton/README +1 -1
  93. data/data/webgen/website_skeleton/config.yaml +5 -4
  94. data/doc/contentprocessor/blocks.page +43 -10
  95. data/doc/contentprocessor/builder.page +1 -1
  96. data/doc/contentprocessor/erb.page +12 -11
  97. data/doc/contentprocessor/redcloth.page +3 -1
  98. data/doc/extensions.page +3 -3
  99. data/doc/faq.page +13 -10
  100. data/doc/getting_started.page +12 -15
  101. data/doc/index.page +7 -1
  102. data/doc/manual.page +78 -27
  103. data/doc/reference_configuration.page +166 -3
  104. data/doc/reference_website_styles.page +28 -0
  105. data/doc/source/filesystem.page +39 -0
  106. data/doc/source/tararchive.page +40 -0
  107. data/doc/tag/tikz.page +2 -1
  108. data/doc/webgen_page_format.page +13 -12
  109. data/doc/website_styles.metainfo +8 -0
  110. data/lib/webgen/blackboard.rb +2 -2
  111. data/lib/webgen/cache.rb +4 -4
  112. data/lib/webgen/cli.rb +29 -16
  113. data/lib/webgen/cli/apply_command.rb +66 -0
  114. data/lib/webgen/cli/create_command.rb +22 -16
  115. data/lib/webgen/cli/utils.rb +23 -0
  116. data/lib/webgen/cli/webgui_command.rb +31 -16
  117. data/lib/webgen/configuration.rb +8 -6
  118. data/lib/webgen/contentprocessor.rb +4 -5
  119. data/lib/webgen/contentprocessor/blocks.rb +2 -0
  120. data/lib/webgen/contentprocessor/builder.rb +6 -3
  121. data/lib/webgen/contentprocessor/erb.rb +6 -3
  122. data/lib/webgen/contentprocessor/erubis.rb +7 -6
  123. data/lib/webgen/contentprocessor/haml.rb +6 -3
  124. data/lib/webgen/contentprocessor/rdoc.rb +0 -1
  125. data/lib/webgen/contentprocessor/redcloth.rb +3 -1
  126. data/lib/webgen/context.rb +73 -0
  127. data/lib/webgen/context/nodes.rb +36 -0
  128. data/lib/webgen/coreext.rb +3 -2
  129. data/lib/webgen/default_config.rb +3 -1
  130. data/lib/webgen/deprecated.rb +53 -0
  131. data/lib/webgen/node.rb +24 -19
  132. data/lib/webgen/output.rb +50 -7
  133. data/lib/webgen/page.rb +45 -36
  134. data/lib/webgen/path.rb +1 -1
  135. data/lib/webgen/source.rb +32 -4
  136. data/lib/webgen/source/resource.rb +3 -3
  137. data/lib/webgen/source/stacked.rb +1 -1
  138. data/lib/webgen/source/tararchive.rb +73 -0
  139. data/lib/webgen/sourcehandler.rb +4 -4
  140. data/lib/webgen/sourcehandler/base.rb +36 -24
  141. data/lib/webgen/sourcehandler/copy.rb +1 -1
  142. data/lib/webgen/sourcehandler/feed.rb +2 -2
  143. data/lib/webgen/sourcehandler/fragment.rb +1 -1
  144. data/lib/webgen/sourcehandler/metainfo.rb +15 -6
  145. data/lib/webgen/sourcehandler/page.rb +9 -5
  146. data/lib/webgen/sourcehandler/virtual.rb +44 -7
  147. data/lib/webgen/tag/base.rb +19 -13
  148. data/lib/webgen/tag/link.rb +1 -0
  149. data/lib/webgen/version.rb +1 -1
  150. data/lib/webgen/webgentask.rb +15 -13
  151. data/lib/webgen/website.rb +42 -11
  152. data/lib/webgen/websiteaccess.rb +1 -1
  153. data/lib/webgen/websitemanager.rb +61 -66
  154. data/man/man1/webgen.1 +4 -0
  155. data/misc/default.css +13 -0
  156. data/misc/default.template +1 -1
  157. data/misc/htmldoc.metainfo +2 -1
  158. data/misc/style.page +33 -0
  159. data/test/test_cli.rb +1 -7
  160. data/test/test_common_sitemap.rb +2 -2
  161. data/test/test_contentprocessor_blocks.rb +14 -1
  162. data/test/test_contentprocessor_builder.rb +3 -1
  163. data/test/test_contentprocessor_erb.rb +3 -2
  164. data/test/test_contentprocessor_erubis.rb +3 -3
  165. data/test/test_contentprocessor_fragments.rb +3 -3
  166. data/test/test_contentprocessor_haml.rb +3 -2
  167. data/test/test_contentprocessor_maruku.rb +3 -3
  168. data/test/test_contentprocessor_rdiscount.rb +1 -1
  169. data/test/test_contentprocessor_rdoc.rb +1 -1
  170. data/test/test_contentprocessor_redcloth.rb +9 -2
  171. data/test/test_contentprocessor_sass.rb +1 -1
  172. data/test/test_contentprocessor_tags.rb +1 -1
  173. data/test/{test_contentprocessor_context.rb → test_context.rb} +9 -7
  174. data/test/test_node.rb +27 -21
  175. data/test/test_page.rb +4 -4
  176. data/test/test_source_tararchive.rb +65 -0
  177. data/test/test_sourcehandler_fragment.rb +1 -1
  178. data/test/test_sourcehandler_memory.rb +6 -6
  179. data/test/test_sourcehandler_metainfo.rb +34 -13
  180. data/test/test_sourcehandler_page.rb +8 -0
  181. data/test/test_sourcehandler_virtual.rb +51 -12
  182. data/test/test_tag_breadcrumbtrail.rb +4 -4
  183. data/test/test_tag_coderay.rb +1 -1
  184. data/test/test_tag_date.rb +1 -1
  185. data/test/test_tag_executecommand.rb +1 -1
  186. data/test/test_tag_includefile.rb +3 -3
  187. data/test/test_tag_langbar.rb +6 -6
  188. data/test/test_tag_link.rb +8 -2
  189. data/test/test_tag_menu.rb +9 -9
  190. data/test/test_tag_metainfo.rb +1 -1
  191. data/test/test_tag_relocatable.rb +1 -1
  192. data/test/test_tag_sitemap.rb +1 -1
  193. data/test/test_tag_tikz.rb +2 -2
  194. data/test/test_website.rb +17 -0
  195. data/test/test_websitemanager.rb +16 -21
  196. metadata +181 -171
  197. data/data/webgen/website_templates/default/README +0 -6
  198. data/data/webgen/website_templates/default/src/index.page +0 -8
  199. data/data/webgen/website_templates/project/README +0 -5
  200. data/data/webgen/website_templates/project/src/about.page +0 -12
  201. data/data/webgen/website_templates/project/src/download.page +0 -15
  202. data/data/webgen/website_templates/project/src/features.page +0 -8
  203. data/data/webgen/website_templates/project/src/index.page +0 -9
  204. data/data/webgen/website_templates/project/src/screenshots.page +0 -18
  205. 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:: Has the node been created or has it been read from the cache?
125
- # :reinit:: Does the node need to be reinitialized?
126
- # :dirty:: Set by other objects to +true+ if they think the object has changed since the last
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:: Set by other objects to +true+ if the meta information of the node has
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
- website.blackboard.dispatch_msg(:node_changed?, self) unless flagged(:dirty)
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
- flag(:dirty_meta_info) if node_info[:used_meta_info_nodes].any? do |n|
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 +:alcn+ or +:acn+.
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: this is only useful when linking to a directory.
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
- # = Implementing an output class
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. The parameter +type+ specifies the type of the
19
- # to be written path: <tt>:file</tt> or <tt>:directory</tt>.
20
- # <tt>read(path)</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 single block within a Page object. The content of the block can be rendered using the #render method.
8
- class Block
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 name of the block.
11
- attr_reader :name
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
- # The content of the block.
14
- attr_reader :content
14
+ # The name of the block.
15
+ attr_reader :name
15
16
 
16
- # The options set specifically for this block.
17
- attr_reader :options
17
+ # The content of the block.
18
+ attr_reader :content
18
19
 
19
- # Create a new block with the name +name+ and the given +content+ and +options+.
20
- def initialize(name, content, options)
21
- @name, @content, @options = name, content, options
22
- end
20
+ # The options set specifically for this block.
21
+ attr_reader :options
23
22
 
24
- # Render the block using the provided context object. Uses the content processors specified in
25
- # the +pipeline+ key of the +options+ attribute to do the actual rendering.
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
- end
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
- # A Page object wraps a meta information hash and an array of Block objects. It is normally
45
- # generated from a file or string in Webgen Page Format using the provided class methods.
46
- class Page
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 WebgenPageFormatError, 'Found start line for meta information block but no valid meta information block'
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 WebgenPageFormatError, "Invalid structure of meta information block: expected YAML hash but found #{meta_info.class}"
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 WebgenPageFormatError, e.message
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(WebgenPageFormatError, 'No content blocks specified') if scanned.length == 0
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(WebgenPageFormatError, "Found invalid blocks starting line for block #{index+1}: #{options}") if content =~ /\A---/ || md.nil?
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(WebgenPageFormatError, "Previously used name '#{name}' also used for block #{index+1}") if blocks.has_key?(name)
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
@@ -109,7 +109,7 @@ module Webgen
109
109
  temp
110
110
  end
111
111
 
112
- # The IO object associated with the path.
112
+ # The SourceIO object associated with the path.
113
113
  def io
114
114
  if @io
115
115
  @io
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
- # = Implementing a source class
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) which is not implemented in the
14
- # default Path class. One can either derive a specialized path class or define singleton methods
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 source provided by resources.
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