thewoolleyman-webgen 0.5.8.20090419

Sign up to get free protection for your applications and to get access to all the features.
Files changed (309) hide show
  1. data/AUTHORS +8 -0
  2. data/COPYING +10 -0
  3. data/GPL +340 -0
  4. data/Rakefile +334 -0
  5. data/THANKS +18 -0
  6. data/bin/webgen +12 -0
  7. data/data/webgen/resources.yaml +3 -0
  8. data/data/webgen/webgui/controller/main.rb +135 -0
  9. data/data/webgen/webgui/overrides/win32console.rb +0 -0
  10. data/data/webgen/webgui/public/css/jquery.autocomplete.css +50 -0
  11. data/data/webgen/webgui/public/css/ramaze_error.css +90 -0
  12. data/data/webgen/webgui/public/css/style.css +55 -0
  13. data/data/webgen/webgui/public/img/headerbg.jpg +0 -0
  14. data/data/webgen/webgui/public/img/webgen_logo.png +0 -0
  15. data/data/webgen/webgui/public/js/jquery.autocomplete.js +15 -0
  16. data/data/webgen/webgui/public/js/jquery.js +32 -0
  17. data/data/webgen/webgui/view/create_website.xhtml +22 -0
  18. data/data/webgen/webgui/view/error.xhtml +64 -0
  19. data/data/webgen/webgui/view/index.xhtml +22 -0
  20. data/data/webgen/webgui/view/manage_website.xhtml +18 -0
  21. data/data/webgen/webgui/view/page.xhtml +40 -0
  22. data/data/webgen/website_skeleton/README +10 -0
  23. data/data/webgen/website_skeleton/Rakefile +40 -0
  24. data/data/webgen/website_skeleton/config.yaml +17 -0
  25. data/data/webgen/website_skeleton/ext/init.rb +10 -0
  26. data/data/webgen/website_styles/1024px/README +13 -0
  27. data/data/webgen/website_styles/1024px/src/default.css +188 -0
  28. data/data/webgen/website_styles/1024px/src/default.template +60 -0
  29. data/data/webgen/website_styles/1024px/src/images/background.gif +0 -0
  30. data/data/webgen/website_styles/andreas00/README +13 -0
  31. data/data/webgen/website_styles/andreas00/src/default.css +290 -0
  32. data/data/webgen/website_styles/andreas00/src/default.template +60 -0
  33. data/data/webgen/website_styles/andreas00/src/images/bg.gif +0 -0
  34. data/data/webgen/website_styles/andreas00/src/images/front.jpg +0 -0
  35. data/data/webgen/website_styles/andreas00/src/images/menubg.gif +0 -0
  36. data/data/webgen/website_styles/andreas00/src/images/menubg2.gif +0 -0
  37. data/data/webgen/website_styles/andreas01/README +14 -0
  38. data/data/webgen/website_styles/andreas01/src/default.css +310 -0
  39. data/data/webgen/website_styles/andreas01/src/default.template +62 -0
  40. data/data/webgen/website_styles/andreas01/src/images/bg.gif +0 -0
  41. data/data/webgen/website_styles/andreas01/src/images/front.jpg +0 -0
  42. data/data/webgen/website_styles/andreas01/src/print.css +35 -0
  43. data/data/webgen/website_styles/andreas03/README +14 -0
  44. data/data/webgen/website_styles/andreas03/src/default.css +223 -0
  45. data/data/webgen/website_styles/andreas03/src/default.template +58 -0
  46. data/data/webgen/website_styles/andreas03/src/images/bodybg.png +0 -0
  47. data/data/webgen/website_styles/andreas03/src/images/contbg.png +0 -0
  48. data/data/webgen/website_styles/andreas03/src/images/footerbg.png +0 -0
  49. data/data/webgen/website_styles/andreas03/src/images/gradient1.png +0 -0
  50. data/data/webgen/website_styles/andreas03/src/images/gradient2.png +0 -0
  51. data/data/webgen/website_styles/andreas04/README +15 -0
  52. data/data/webgen/website_styles/andreas04/src/default.css +290 -0
  53. data/data/webgen/website_styles/andreas04/src/default.template +81 -0
  54. data/data/webgen/website_styles/andreas04/src/images/blinkarrow.gif +0 -0
  55. data/data/webgen/website_styles/andreas04/src/images/bodybg.png +0 -0
  56. data/data/webgen/website_styles/andreas04/src/images/contentbg.png +0 -0
  57. data/data/webgen/website_styles/andreas04/src/images/entrybg.png +0 -0
  58. data/data/webgen/website_styles/andreas04/src/images/flash.gif +0 -0
  59. data/data/webgen/website_styles/andreas04/src/images/flash2.gif +0 -0
  60. data/data/webgen/website_styles/andreas04/src/images/globe.gif +0 -0
  61. data/data/webgen/website_styles/andreas04/src/images/globebottom.gif +0 -0
  62. data/data/webgen/website_styles/andreas04/src/images/linkarrow.gif +0 -0
  63. data/data/webgen/website_styles/andreas04/src/images/menuhover.png +0 -0
  64. data/data/webgen/website_styles/andreas05/README +14 -0
  65. data/data/webgen/website_styles/andreas05/src/default.css +33 -0
  66. data/data/webgen/website_styles/andreas05/src/default.template +40 -0
  67. data/data/webgen/website_styles/andreas05/src/images/bodybg.gif +0 -0
  68. data/data/webgen/website_styles/andreas05/src/images/front.png +0 -0
  69. data/data/webgen/website_styles/andreas06/README +14 -0
  70. data/data/webgen/website_styles/andreas06/src/default.css +354 -0
  71. data/data/webgen/website_styles/andreas06/src/default.template +70 -0
  72. data/data/webgen/website_styles/andreas06/src/images/bodybg.gif +0 -0
  73. data/data/webgen/website_styles/andreas06/src/images/boxbg.gif +0 -0
  74. data/data/webgen/website_styles/andreas06/src/images/greypx.gif +0 -0
  75. data/data/webgen/website_styles/andreas06/src/images/header.jpg +0 -0
  76. data/data/webgen/website_styles/andreas06/src/images/innerbg.gif +0 -0
  77. data/data/webgen/website_styles/andreas06/src/images/leaves.jpg +0 -0
  78. data/data/webgen/website_styles/andreas06/src/images/tabs.gif +0 -0
  79. data/data/webgen/website_styles/andreas07/README +15 -0
  80. data/data/webgen/website_styles/andreas07/src/browserfix.css +7 -0
  81. data/data/webgen/website_styles/andreas07/src/default.css +92 -0
  82. data/data/webgen/website_styles/andreas07/src/default.template +42 -0
  83. data/data/webgen/website_styles/andreas07/src/images/bodybg.gif +0 -0
  84. data/data/webgen/website_styles/andreas07/src/images/sidebarbg.gif +0 -0
  85. data/data/webgen/website_styles/andreas08/README +14 -0
  86. data/data/webgen/website_styles/andreas08/src/default.css +224 -0
  87. data/data/webgen/website_styles/andreas08/src/default.template +51 -0
  88. data/data/webgen/website_styles/andreas09/README +14 -0
  89. data/data/webgen/website_styles/andreas09/src/default.css +308 -0
  90. data/data/webgen/website_styles/andreas09/src/default.template +68 -0
  91. data/data/webgen/website_styles/andreas09/src/images/bodybg-black.jpg +0 -0
  92. data/data/webgen/website_styles/andreas09/src/images/bodybg-green.jpg +0 -0
  93. data/data/webgen/website_styles/andreas09/src/images/bodybg-orange.jpg +0 -0
  94. data/data/webgen/website_styles/andreas09/src/images/bodybg-purple.jpg +0 -0
  95. data/data/webgen/website_styles/andreas09/src/images/bodybg-red.jpg +0 -0
  96. data/data/webgen/website_styles/andreas09/src/images/bodybg.jpg +0 -0
  97. data/data/webgen/website_styles/andreas09/src/images/footerbg.jpg +0 -0
  98. data/data/webgen/website_styles/andreas09/src/images/menuhover-black.jpg +0 -0
  99. data/data/webgen/website_styles/andreas09/src/images/menuhover-green.jpg +0 -0
  100. data/data/webgen/website_styles/andreas09/src/images/menuhover-orange.jpg +0 -0
  101. data/data/webgen/website_styles/andreas09/src/images/menuhover-purple.jpg +0 -0
  102. data/data/webgen/website_styles/andreas09/src/images/menuhover-red.jpg +0 -0
  103. data/data/webgen/website_styles/andreas09/src/images/menuhover.jpg +0 -0
  104. data/data/webgen/website_styles/simple/README +6 -0
  105. data/data/webgen/website_styles/simple/src/default.css +84 -0
  106. data/data/webgen/website_styles/simple/src/default.template +36 -0
  107. data/data/webgen/website_templates/default/README +6 -0
  108. data/data/webgen/website_templates/default/src/index.page +8 -0
  109. data/data/webgen/website_templates/project/README +5 -0
  110. data/data/webgen/website_templates/project/src/about.page +12 -0
  111. data/data/webgen/website_templates/project/src/download.page +15 -0
  112. data/data/webgen/website_templates/project/src/features.page +8 -0
  113. data/data/webgen/website_templates/project/src/index.page +9 -0
  114. data/data/webgen/website_templates/project/src/screenshots.page +18 -0
  115. data/doc/contentprocessor.template +11 -0
  116. data/doc/contentprocessor/blocks.page +129 -0
  117. data/doc/contentprocessor/builder.page +80 -0
  118. data/doc/contentprocessor/erb.page +59 -0
  119. data/doc/contentprocessor/erubis.page +46 -0
  120. data/doc/contentprocessor/fragments.page +25 -0
  121. data/doc/contentprocessor/haml.page +47 -0
  122. data/doc/contentprocessor/maruku.page +41 -0
  123. data/doc/contentprocessor/rdiscount.page +37 -0
  124. data/doc/contentprocessor/rdoc.page +36 -0
  125. data/doc/contentprocessor/redcloth.page +39 -0
  126. data/doc/contentprocessor/sass.page +31 -0
  127. data/doc/contentprocessor/tags.page +73 -0
  128. data/doc/extensions.metainfo +29 -0
  129. data/doc/extensions.page +16 -0
  130. data/doc/extensions.template +17 -0
  131. data/doc/faq.page +219 -0
  132. data/doc/getting_started.page +135 -0
  133. data/doc/index.page +65 -0
  134. data/doc/manual.page +589 -0
  135. data/doc/reference_configuration.page +959 -0
  136. data/doc/reference_metainfo.page +222 -0
  137. data/doc/source/filesystem.page +39 -0
  138. data/doc/source/tararchive.page +40 -0
  139. data/doc/sourcehandler.template +21 -0
  140. data/doc/sourcehandler/copy.page +19 -0
  141. data/doc/sourcehandler/directory.page +27 -0
  142. data/doc/sourcehandler/feed.page +105 -0
  143. data/doc/sourcehandler/metainfo.page +41 -0
  144. data/doc/sourcehandler/page.page +14 -0
  145. data/doc/sourcehandler/sitemap.page +46 -0
  146. data/doc/sourcehandler/template.page +45 -0
  147. data/doc/sourcehandler/virtual.page +49 -0
  148. data/doc/tag.template +25 -0
  149. data/doc/tag/breadcrumbtrail.page +40 -0
  150. data/doc/tag/coderay.page +49 -0
  151. data/doc/tag/date.page +31 -0
  152. data/doc/tag/executecommand.page +26 -0
  153. data/doc/tag/includefile.page +32 -0
  154. data/doc/tag/langbar.page +44 -0
  155. data/doc/tag/link.page +44 -0
  156. data/doc/tag/menu.page +106 -0
  157. data/doc/tag/metainfo.page +29 -0
  158. data/doc/tag/relocatable.page +38 -0
  159. data/doc/tag/sitemap.page +31 -0
  160. data/doc/tag/tikz.page +158 -0
  161. data/doc/upgrading.page +139 -0
  162. data/doc/webgen_page_format.page +129 -0
  163. data/lib/webgen/blackboard.rb +78 -0
  164. data/lib/webgen/cache.rb +87 -0
  165. data/lib/webgen/cli.rb +124 -0
  166. data/lib/webgen/cli/apply_command.rb +64 -0
  167. data/lib/webgen/cli/create_command.rb +66 -0
  168. data/lib/webgen/cli/run_command.rb +22 -0
  169. data/lib/webgen/cli/utils.rb +88 -0
  170. data/lib/webgen/cli/webgui_command.rb +72 -0
  171. data/lib/webgen/common.rb +21 -0
  172. data/lib/webgen/common/sitemap.rb +83 -0
  173. data/lib/webgen/configuration.rb +153 -0
  174. data/lib/webgen/contentprocessor.rb +99 -0
  175. data/lib/webgen/contentprocessor/blocks.rb +60 -0
  176. data/lib/webgen/contentprocessor/builder.rb +30 -0
  177. data/lib/webgen/contentprocessor/context.rb +89 -0
  178. data/lib/webgen/contentprocessor/erb.rb +28 -0
  179. data/lib/webgen/contentprocessor/erubis.rb +40 -0
  180. data/lib/webgen/contentprocessor/fragments.rb +25 -0
  181. data/lib/webgen/contentprocessor/haml.rb +30 -0
  182. data/lib/webgen/contentprocessor/maruku.rb +20 -0
  183. data/lib/webgen/contentprocessor/rdiscount.rb +17 -0
  184. data/lib/webgen/contentprocessor/rdoc.rb +19 -0
  185. data/lib/webgen/contentprocessor/redcloth.rb +17 -0
  186. data/lib/webgen/contentprocessor/sass.rb +20 -0
  187. data/lib/webgen/contentprocessor/tags.rb +136 -0
  188. data/lib/webgen/coreext.rb +13 -0
  189. data/lib/webgen/default_config.rb +215 -0
  190. data/lib/webgen/languages.rb +589 -0
  191. data/lib/webgen/loggable.rb +25 -0
  192. data/lib/webgen/logger.rb +97 -0
  193. data/lib/webgen/node.rb +391 -0
  194. data/lib/webgen/output.rb +82 -0
  195. data/lib/webgen/output/filesystem.rb +69 -0
  196. data/lib/webgen/page.rb +153 -0
  197. data/lib/webgen/path.rb +194 -0
  198. data/lib/webgen/source.rb +54 -0
  199. data/lib/webgen/source/filesystem.rb +61 -0
  200. data/lib/webgen/source/resource.rb +44 -0
  201. data/lib/webgen/source/stacked.rb +55 -0
  202. data/lib/webgen/source/tararchive.rb +73 -0
  203. data/lib/webgen/sourcehandler.rb +226 -0
  204. data/lib/webgen/sourcehandler/base.rb +248 -0
  205. data/lib/webgen/sourcehandler/copy.rb +43 -0
  206. data/lib/webgen/sourcehandler/directory.rb +36 -0
  207. data/lib/webgen/sourcehandler/feed.rb +117 -0
  208. data/lib/webgen/sourcehandler/fragment.rb +68 -0
  209. data/lib/webgen/sourcehandler/memory.rb +43 -0
  210. data/lib/webgen/sourcehandler/metainfo.rb +128 -0
  211. data/lib/webgen/sourcehandler/page.rb +59 -0
  212. data/lib/webgen/sourcehandler/sitemap.rb +60 -0
  213. data/lib/webgen/sourcehandler/template.rb +66 -0
  214. data/lib/webgen/sourcehandler/virtual.rb +110 -0
  215. data/lib/webgen/tag.rb +27 -0
  216. data/lib/webgen/tag/base.rb +170 -0
  217. data/lib/webgen/tag/breadcrumbtrail.rb +70 -0
  218. data/lib/webgen/tag/coderay.rb +31 -0
  219. data/lib/webgen/tag/date.rb +18 -0
  220. data/lib/webgen/tag/executecommand.rb +30 -0
  221. data/lib/webgen/tag/includefile.rb +42 -0
  222. data/lib/webgen/tag/langbar.rb +52 -0
  223. data/lib/webgen/tag/link.rb +26 -0
  224. data/lib/webgen/tag/menu.rb +207 -0
  225. data/lib/webgen/tag/metainfo.rb +25 -0
  226. data/lib/webgen/tag/relocatable.rb +54 -0
  227. data/lib/webgen/tag/sitemap.rb +41 -0
  228. data/lib/webgen/tag/tikz.rb +119 -0
  229. data/lib/webgen/tree.rb +90 -0
  230. data/lib/webgen/version.rb +8 -0
  231. data/lib/webgen/webgentask.rb +152 -0
  232. data/lib/webgen/website.rb +342 -0
  233. data/lib/webgen/websiteaccess.rb +31 -0
  234. data/lib/webgen/websitemanager.rb +127 -0
  235. data/man/man1/webgen.1 +73 -0
  236. data/misc/default.css +384 -0
  237. data/misc/default.template +75 -0
  238. data/misc/htmldoc.metainfo +25 -0
  239. data/misc/htmldoc.virtual +5 -0
  240. data/misc/images/arrow.gif +0 -0
  241. data/misc/images/error.png +0 -0
  242. data/misc/images/headerbg.jpg +0 -0
  243. data/misc/images/important.png +0 -0
  244. data/misc/images/information.png +0 -0
  245. data/misc/images/quote.gif +0 -0
  246. data/misc/images/warning.png +0 -0
  247. data/setup.rb +1585 -0
  248. data/test/helper.rb +45 -0
  249. data/test/test_blackboard.rb +60 -0
  250. data/test/test_cache.rb +59 -0
  251. data/test/test_cli.rb +21 -0
  252. data/test/test_common.rb +18 -0
  253. data/test/test_common_sitemap.rb +58 -0
  254. data/test/test_configuration.rb +68 -0
  255. data/test/test_contentprocessor.rb +33 -0
  256. data/test/test_contentprocessor_blocks.rb +68 -0
  257. data/test/test_contentprocessor_builder.rb +23 -0
  258. data/test/test_contentprocessor_context.rb +40 -0
  259. data/test/test_contentprocessor_erb.rb +23 -0
  260. data/test/test_contentprocessor_erubis.rb +49 -0
  261. data/test/test_contentprocessor_fragments.rb +42 -0
  262. data/test/test_contentprocessor_haml.rb +23 -0
  263. data/test/test_contentprocessor_maruku.rb +29 -0
  264. data/test/test_contentprocessor_rdiscount.rb +17 -0
  265. data/test/test_contentprocessor_rdoc.rb +18 -0
  266. data/test/test_contentprocessor_redcloth.rb +15 -0
  267. data/test/test_contentprocessor_sass.rb +22 -0
  268. data/test/test_contentprocessor_tags.rb +99 -0
  269. data/test/test_languages.rb +67 -0
  270. data/test/test_loggable.rb +32 -0
  271. data/test/test_logger.rb +94 -0
  272. data/test/test_node.rb +367 -0
  273. data/test/test_output_filesystem.rb +60 -0
  274. data/test/test_page.rb +214 -0
  275. data/test/test_path.rb +165 -0
  276. data/test/test_source_filesystem.rb +76 -0
  277. data/test/test_source_resource.rb +28 -0
  278. data/test/test_source_stacked.rb +36 -0
  279. data/test/test_source_tararchive.rb +65 -0
  280. data/test/test_sourcehandler_base.rb +123 -0
  281. data/test/test_sourcehandler_copy.rb +47 -0
  282. data/test/test_sourcehandler_directory.rb +42 -0
  283. data/test/test_sourcehandler_feed.rb +77 -0
  284. data/test/test_sourcehandler_fragment.rb +69 -0
  285. data/test/test_sourcehandler_memory.rb +44 -0
  286. data/test/test_sourcehandler_metainfo.rb +118 -0
  287. data/test/test_sourcehandler_page.rb +65 -0
  288. data/test/test_sourcehandler_sitemap.rb +49 -0
  289. data/test/test_sourcehandler_template.rb +65 -0
  290. data/test/test_sourcehandler_virtual.rb +87 -0
  291. data/test/test_tag_base.rb +85 -0
  292. data/test/test_tag_breadcrumbtrail.rb +91 -0
  293. data/test/test_tag_coderay.rb +32 -0
  294. data/test/test_tag_date.rb +18 -0
  295. data/test/test_tag_executecommand.rb +41 -0
  296. data/test/test_tag_includefile.rb +50 -0
  297. data/test/test_tag_langbar.rb +72 -0
  298. data/test/test_tag_link.rb +69 -0
  299. data/test/test_tag_menu.rb +207 -0
  300. data/test/test_tag_metainfo.rb +19 -0
  301. data/test/test_tag_relocatable.rb +59 -0
  302. data/test/test_tag_sitemap.rb +47 -0
  303. data/test/test_tag_tikz.rb +69 -0
  304. data/test/test_tree.rb +70 -0
  305. data/test/test_webgentask.rb +23 -0
  306. data/test/test_website.rb +98 -0
  307. data/test/test_websiteaccess.rb +25 -0
  308. data/test/test_websitemanager.rb +70 -0
  309. metadata +613 -0
@@ -0,0 +1,248 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'facets/symbol/to_proc'
4
+ require 'webgen/websiteaccess'
5
+ require 'webgen/loggable'
6
+ require 'webgen/page'
7
+
8
+ module Webgen::SourceHandler
9
+
10
+ # This module should be included in every source handler as it provides the default methods for
11
+ # creating nodes.
12
+ #
13
+ # == Implementing Source Handlers
14
+ #
15
+ # A source handler is a webgen extension that processes source paths to create nodes and that
16
+ # provides the rendered content of these nodes. The nodes are later written to the output
17
+ # location. This can range from simply copying a path from the source to the output location to
18
+ # generating a whole set of nodes from one input path!
19
+ #
20
+ # The paths that are handled by a source handler are specified via path patterns (see
21
+ # below). During a webgen run the #create_node method for each source paths that matches a
22
+ # specified path pattern is called. And when it is time to write out the node, the the #content
23
+ # method is called to retrieve the rendered content.
24
+ #
25
+ # A source handler must not take any parameters on initialization and when this module is not
26
+ # mixed in, the methods #create_node and #content need to be defined. Also, a source handler does
27
+ # not need to reside under the Webgen::SourceHandler namespace but all shipped ones do.
28
+ #
29
+ # This base class provides useful default implementations of methods that are used by nearly all
30
+ # source handler classes:
31
+ # * #create_node
32
+ # * #output_path
33
+ # * #node_exists?
34
+ #
35
+ # It also provides other utility methods:
36
+ # * #page_from_path
37
+ # * #content
38
+ #
39
+ # == Nodes Created for Paths
40
+ #
41
+ # The main functions of a source handler class are to create one or more nodes for a source path
42
+ # and to provide the content of these nodes. To achieve this, certain information needs to be set
43
+ # on a created node. If you use the +create_node+ method provided by this base class, you don't
44
+ # need to set them explicitly because this is done by the method:
45
+ #
46
+ # [<tt>node_info[:processor]</tt>] Has to be set to the class name of the source handler. This is
47
+ # used by the Node class: all unknown method calls are forwarded
48
+ # to the node processor.
49
+ # [<tt>node_info[:src]</tt>] Has to be set to the string version of the path that lead to the
50
+ # creation of the node.
51
+ # [<tt>node_info[:creation_path]</tt>] Has to be set to the string version of the path that is
52
+ # used to create the path.
53
+ # [<tt>meta_info['no_output']</tt>] Has to be set to +true+ on nodes that are used during a
54
+ # webgen run but do not produce an output file.
55
+ # [<tt>meta_info['modified_at']</tt>] Has to be set to the current time if not already set
56
+ # correctly (ie. if not a Time object).
57
+ #
58
+ # If <tt>meta_info['draft']</tt> is set on a path, then no node should be created in +create_node+
59
+ # and +nil+ has to be returned.
60
+ #
61
+ # Note: The difference between +:src+ and +:creation_path+ is that a creation path
62
+ # need not have an existing source path representation. For example, fragments created from a page
63
+ # source path have a different +:creation_path+ which includes the fragment part.
64
+ #
65
+ # Additional information that is used only for processing purposes should be stored in the
66
+ # #node_info hash of a node as the #meta_info hash is reserved for real node meta information and
67
+ # should not be changed once the node is created.
68
+ #
69
+ # == Output Path Names
70
+ #
71
+ # The method for creating an output path name for a source path is stored in the meta information
72
+ # +output_path+. If you don't use the provided method +output_path+, have a look at its
73
+ # implementation to see how to an output path gets created. Individual output path creation
74
+ # methods are stored as methods in the OutputPathHelpers module.
75
+ #
76
+ # == Path Patterns and Invocation order
77
+ #
78
+ # Path patterns define which paths are handled by a specific source handler. These patterns are
79
+ # specified in the <tt>sourcehandler.patterns</tt> configuration hash as a mapping from the source
80
+ # handler class name to an array of path patterns. The patterns need to have a format that
81
+ # <tt>Dir.glob</tt> can handle. You can use the configuration helper +patterns+ to set this (is
82
+ # shown in the example below).
83
+ #
84
+ # Specifying a path pattern does not mean that webgen uses the source handler. One also needs to
85
+ # provide an entry in the configuration value <tt>sourcehandler.invoke</tt>. This is a hash that
86
+ # maps the invocation rank (a number) to an array of source handler class names. The lower the
87
+ # invocation rank the earlier the specified source handlers are used.
88
+ #
89
+ # The default invocation ranks are:
90
+ # [1] Early. Normally there is no need to use this rank.
91
+ # [5] Standard. This is the rank the normal source handler should use.
92
+ # [9] Late. This rank should be used by source handlers that operate on/use already created nodes
93
+ # and need to ensure that these nodes are available.
94
+ #
95
+ # == Default Meta Information
96
+ #
97
+ # Each source handler can define default meta information that gets automatically set on the
98
+ # source paths that are passed to the #create_node method.
99
+ #
100
+ # The default meta information is specified in the <tt>sourcehandler.default_meta_info</tt>
101
+ # configuration hash as a mapping from the source handler class name to the meta information
102
+ # hash.
103
+ #
104
+ # == Sample Source Handler Class
105
+ #
106
+ # Following is a simple source handler class example which copies paths from the source to
107
+ # the output location modifying the extension:
108
+ #
109
+ # class SimpleCopy
110
+ #
111
+ # include Webgen::SourceHandler::Base
112
+ #
113
+ # def create_node(parent, path)
114
+ # path.ext += '.copied'
115
+ # super(parent, path)
116
+ # end
117
+ #
118
+ # def content(node)
119
+ # website.blackboard.invoke(:source_paths)[node.node_info[:src]].io
120
+ # end
121
+ #
122
+ # end
123
+ #
124
+ # WebsiteAccess.website.config.patterns('SimpleCopy' => ['**/*.jpg', '**/*.png'])
125
+ # WebsiteAccess.website.config.sourcehandler.invoke[5] << 'SimpleCopy'
126
+ #
127
+ module Base
128
+
129
+ # This module is used for defining all methods that can be used for creating output paths.
130
+ #
131
+ # All public methods of this module are considered to be output path creation methods and must
132
+ # have the following parameters:
133
+ #
134
+ # [+parent+] the parent node
135
+ # [+path+] the path for which the output name should be created
136
+ # [+use_lang_part+] controls whether the output path name has to include the language part
137
+ module OutputPathHelpers
138
+
139
+ # Default method for creating an output path for +parent+ and source +path+.
140
+ #
141
+ # The automatically set parameter +style+ (which uses the meta information +output_path_style+
142
+ # from the path's meta information hash) defines how the output name should be built (more
143
+ # information about this in the user documentation).
144
+ def standard_output_path(parent, path, use_lang_part, style = path.meta_info['output_path_style'])
145
+ result = style.collect do |part|
146
+ case part
147
+ when String then part
148
+ when :lang then use_lang_part ? path.meta_info['lang'] : ''
149
+ when :ext then path.ext.empty? ? '' : '.' + path.ext
150
+ when :parent then temp = parent; temp = temp.parent while temp.is_fragment?; temp.path
151
+ when :year, :month, :day
152
+ ctime = path.meta_info['created_at']
153
+ if !ctime.kind_of?(Time)
154
+ raise "Invalid meta info 'created_at' for #{path}, needed because of used output path style"
155
+ end
156
+ ctime.send(part).to_s.rjust(2, '0')
157
+ when Symbol then path.send(part)
158
+ when Array then part.include?(:lang) && !use_lang_part ? '' : standard_output_path(parent, path, use_lang_part, part)
159
+ else ''
160
+ end
161
+ end
162
+ result.join('')
163
+ end
164
+
165
+ end
166
+
167
+ include Webgen::Loggable
168
+ include OutputPathHelpers
169
+
170
+ # Construct the output name for the given +path+ and +parent+. First it is checked if a node
171
+ # with the constructed output name already exists. If it exists, the language part is forced to
172
+ # be in the output name and the resulting output name is returned.
173
+ def output_path(parent, path)
174
+ method = path.meta_info['output_path'] + '_output_path'
175
+ use_lang_part = if path.meta_info['lang'].nil? # unlocalized files never get a lang in the filename!
176
+ false
177
+ else
178
+ Webgen::WebsiteAccess.website.config['sourcehandler.default_lang_in_output_path'] ||
179
+ Webgen::WebsiteAccess.website.config['website.lang'] != path.meta_info['lang']
180
+ end
181
+ if OutputPathHelpers.public_instance_methods(false).map(&:to_s).include?(method)
182
+ name = send(method, parent, path, use_lang_part)
183
+ name += '/' if path.path =~ /\/$/ && name !~ /\/$/
184
+ if (node = node_exists?(parent, path, name)) && node.lang == path.meta_info['lang']
185
+ name = node.path
186
+ elsif node
187
+ name = send(method, parent, path, (path.meta_info['lang'].nil? ? false : true))
188
+ name += '/' if path.path =~ /\/$/ && name !~ /\/$/
189
+ end
190
+ name
191
+ else
192
+ raise "Unknown method for creating output path: #{method}"
193
+ end
194
+ end
195
+
196
+ # Check if the node alcn and output path which would be created by #create_node exists. The
197
+ # +output_path+ to check for can individually be set.
198
+ def node_exists?(parent, path, output_path = self.output_path(parent, path))
199
+ parent.tree[Webgen::Node.absolute_name(parent, path.lcn, :alcn)] || (!path.meta_info['no_output'] && parent.tree[output_path, :path])
200
+ end
201
+
202
+ # Create a node under +parent+ from +path+ if it does not already exists or needs to be
203
+ # re-initialized. The found node or the newly created node is returned afterwards. +nil+ is
204
+ # returned if no node can be created (e.g. when <tt>path.meta_info['draft']</tt> is set). Some
205
+ # additional node information like <tt>:src</tt> and <tt>:processor</tt> is set and the meta
206
+ # information is checked for validness. The created/re-initialized node is yielded if a block is
207
+ # given.
208
+ def create_node(parent, path, output_path = self.output_path(parent, path))
209
+ return nil if path.meta_info['draft']
210
+ node = node_exists?(parent, path, output_path)
211
+ if node && (node.node_info[:src] != path.source_path || node.node_info[:processor] != self.class.name)
212
+ log(:warn) { "Node already exists: source = #{path.source_path} | path = #{node.path} | alcn = #{node.absolute_lcn}"}
213
+ return node
214
+ elsif !node
215
+ node = Webgen::Node.new(parent, output_path, path.cn, path.meta_info)
216
+ elsif node.flagged(:reinit)
217
+ node.reinit(output_path, path.meta_info)
218
+ else
219
+ return node
220
+ end
221
+ node['modified_at'] = Time.now unless node['modified_at'].kind_of?(Time)
222
+ node.node_info[:src] = path.source_path
223
+ node.node_info[:creation_path] = path.path
224
+ node.node_info[:processor] = self.class.name
225
+ yield(node) if block_given?
226
+ node
227
+ end
228
+
229
+ # Return the content of the given +node+. This default +content+ method just returns +nil+.
230
+ def content(node)
231
+ nil
232
+ end
233
+
234
+ # Utility method for creating a Webgen::Page object from the +path+. Also updates
235
+ # <tt>path.meta_info</tt> with the meta info from the page.
236
+ def page_from_path(path)
237
+ begin
238
+ page = Webgen::Page.from_data(path.io.data, path.meta_info)
239
+ rescue Webgen::WebgenPageFormatError => e
240
+ raise "Error reading source path <#{path}>: #{e.message}"
241
+ end
242
+ path.meta_info = page.meta_info
243
+ page
244
+ end
245
+
246
+ end
247
+
248
+ end
@@ -0,0 +1,43 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Webgen::SourceHandler
4
+
5
+ # Simple source handler for copying files from the source tree, either verbatim or by applying a
6
+ # content processor.
7
+ class Copy
8
+
9
+ include Webgen::WebsiteAccess
10
+ include Base
11
+
12
+ # Create the node for +parent+ and +path+. If the +path+ has the name of a content processor as
13
+ # the first part in the extension, it is preprocessed.
14
+ def create_node(parent, path)
15
+ if path.ext.index('.')
16
+ processor, *rest = path.ext.split('.')
17
+ if website.blackboard.invoke(:content_processor_names).include?(processor)
18
+ path.ext = rest.join('.')
19
+ else
20
+ processor = nil
21
+ end
22
+ end
23
+ super(parent, path) do |node|
24
+ node.node_info[:preprocessor] = processor
25
+ end
26
+ end
27
+
28
+ # Return either the preprocessed content of the +node+ or the IO object for the node's source
29
+ # path depending on the node type.
30
+ def content(node)
31
+ io = website.blackboard.invoke(:source_paths)[node.node_info[:src]].io
32
+ if node.node_info[:preprocessor]
33
+ context = Webgen::ContentProcessor::Context.new(:content => io.data, :chain => [node])
34
+ website.blackboard.invoke(:content_processor, node.node_info[:preprocessor]).call(context)
35
+ context.content
36
+ else
37
+ io
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Webgen::SourceHandler
4
+
5
+ # Handles directory source paths.
6
+ class Directory
7
+
8
+ include Base
9
+ include Webgen::WebsiteAccess
10
+
11
+ def initialize # :nodoc:
12
+ website.blackboard.add_service(:create_directories, method(:create_directories))
13
+ end
14
+
15
+ # Recursively create the directories specified in +dirname+ under +parent+ (a leading slash is
16
+ # ignored). The path +path+ is the path that lead to the creation of these directories.
17
+ def create_directories(parent, dirname, path)
18
+ dirname.sub(/^\//, '').split('/').each do |dir|
19
+ dir_path = Webgen::Path.new(File.join(parent.absolute_lcn, dir, '/'), path)
20
+ nodes = website.blackboard.invoke(:create_nodes, parent.tree, parent.absolute_lcn,
21
+ dir_path, self) do |dir_parent, dir_path|
22
+ node_exists?(dir_parent, dir_path) || create_node(dir_parent, dir_path)
23
+ end
24
+ parent = nodes.first
25
+ end
26
+ parent
27
+ end
28
+
29
+ # Return an empty string to signal that the directory should be written to the output.
30
+ def content(node)
31
+ ''
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,117 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Webgen::SourceHandler
4
+
5
+ # Source handler for creating atom and/or rss feeds.
6
+ class Feed
7
+
8
+ include Webgen::WebsiteAccess
9
+ include Base
10
+
11
+ # The mandatory keys that need to be set in a feed file.
12
+ MANDATORY_INFOS = %W[site_url author entries]
13
+
14
+ def initialize # :nodoc:
15
+ website.blackboard.add_listener(:node_changed?, method(:node_changed?))
16
+ end
17
+
18
+ # Create atom and/or rss feed files from +parent+ and +path+.
19
+ def create_node(parent, path)
20
+ page = page_from_path(path)
21
+ path.meta_info['link'] ||= parent.absolute_lcn
22
+
23
+ if MANDATORY_INFOS.any? {|t| path.meta_info[t].nil?}
24
+ raise "One of #{MANDATORY_INFOS.join('/')} information missing for feed <#{path}>"
25
+ end
26
+
27
+ create_feed_node = lambda do |type|
28
+ path.ext = type
29
+ super(parent, path) do |node|
30
+ node.node_info[:feed] = page
31
+ node.node_info[:feed_type] = type
32
+ end
33
+ end
34
+
35
+ nodes = []
36
+ nodes << create_feed_node['atom'] if path.meta_info['atom']
37
+ nodes << create_feed_node['rss'] if path.meta_info['rss']
38
+
39
+ nodes
40
+ end
41
+
42
+ # Return the rendered feed represented by +node+.
43
+ def content(node)
44
+ website.cache[[:sourcehandler_feed, node.node_info[:src]]] = feed_entries(node).map {|n| n.absolute_lcn}
45
+ block_name = node.node_info[:feed_type] + '_template'
46
+ if node.node_info[:feed].blocks.has_key?(block_name)
47
+ node.node_info[:feed].blocks[block_name].
48
+ render(Webgen::ContentProcessor::Context.new(:chain => [node])).content
49
+ else
50
+ feed = (website.cache.volatile[:sourcehandler_feed] ||= {})[node.node_info[:src]] ||= build_feed_for(node)
51
+ feed.build_xml(node.node_info[:feed_type], (node.node_info[:feed_type] == 'rss' ? node['rss_version'] || 2.0 : nil))
52
+ end
53
+ end
54
+
55
+ # Helper method for returning the entries for the feed node +node+.
56
+ def feed_entries(node)
57
+ nr_items = (node['number_of_entries'].to_i == 0 ? 10 : node['number_of_entries'].to_i)
58
+ patterns = [node['entries']].flatten.map {|pat| Webgen::Common.absolute_path(pat, node.parent.absolute_lcn)}
59
+
60
+ node.tree.node_access[:alcn].values.
61
+ select {|node| patterns.any? {|pat| node =~ pat} && node.node_info[:page]}.
62
+ sort {|a,b| a['modified_at'] <=> b['modified_at']}[0, nr_items]
63
+ end
64
+
65
+ #######
66
+ private
67
+ #######
68
+
69
+ # Return the populated FeedTools::Feed object for +node+.
70
+ def build_feed_for(node)
71
+ require 'feed_tools'
72
+ require 'time'
73
+
74
+ site_url = node['site_url']
75
+
76
+ feed = FeedTools::Feed.new
77
+ feed.title = node['title']
78
+ feed.description = node['description']
79
+ feed.author = node['author']
80
+ feed.author.url = node['author_url']
81
+ feed.base_uri = site_url
82
+ feed.link = File.join(site_url, node.tree[node['link']].path)
83
+ feed.id = feed.link
84
+
85
+ feed.published = (node['created_at'].kind_of?(Time) ? node['created_at'] : Time.now)
86
+ feed.updated = Time.now
87
+ feed.generator = 'webgen - Webgen::SourceHandler::Feed'
88
+
89
+ node.feed_entries.each do |entry|
90
+ item = FeedTools::FeedItem.new
91
+ item.title = entry['title']
92
+ item.link = File.join(site_url, entry.path)
93
+ item.content = entry.node_info[:page].blocks[node['content_block_name'] || 'content'].render(Webgen::ContentProcessor::Context.new(:chain => [entry])).content
94
+ item.updated = entry['modified_at']
95
+ item.published = entry['created_at'] if entry['created_at'].kind_of?(Time)
96
+ if entry['author']
97
+ item.author = entry['author']
98
+ item.author.url = entry['author_url']
99
+ end
100
+ item.id = item.link
101
+ feed << item
102
+ end
103
+ feed
104
+ end
105
+
106
+ # Check if the any of the nodes used by this feed +node+ have changed and then mark the node as
107
+ # dirty.
108
+ def node_changed?(node)
109
+ return if node.node_info[:processor] != self.class.name
110
+ entries = node.feed_entries
111
+ node.flag(:dirty) if entries.map {|n| n.absolute_lcn } != website.cache[[:sourcehandler_feed, node.node_info[:src]]] ||
112
+ entries.any? {|n| n.changed?}
113
+ end
114
+
115
+ end
116
+
117
+ end
@@ -0,0 +1,68 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Webgen::SourceHandler
4
+
5
+ # Handles page fragment nodes and provides utility methods for parsing HTML headers and generating
6
+ # fragment nodes from them.
7
+ class Fragment
8
+
9
+ include Base
10
+ include Webgen::WebsiteAccess
11
+
12
+ HTML_HEADER_REGEXP = /<h([123456])(?:>|\s([^>]*)>)(.*?)<\/h\1\s*>/i
13
+ HTML_ATTR_REGEXP = /\s*(\w+)\s*=\s*('|")([^\2]+)\2\s*/
14
+
15
+ # Parse the string +content+ for headers +h1+, ..., +h6+ and return the found, nested sections.
16
+ #
17
+ # Only those headers are used which have an +id+ attribute set. The method returns a list of
18
+ # arrays with entries <tt>level, id, title, sub sections</tt> where <tt>sub sections</tt> is
19
+ # such a list again.
20
+ def parse_html_headers(content)
21
+ sections = []
22
+ stack = []
23
+ content.scan(HTML_HEADER_REGEXP).each do |level,attrs,title|
24
+ next if attrs.nil?
25
+ id_attr = attrs.scan(HTML_ATTR_REGEXP).find {|name,sep,value| name == 'id'}
26
+ next if id_attr.nil?
27
+ id = id_attr[2]
28
+
29
+ section = [level.to_i, id, title, []]
30
+ success = false
31
+ while !success
32
+ if stack.empty?
33
+ sections << section
34
+ stack << section
35
+ success = true
36
+ elsif stack.last.first < section.first
37
+ stack.last.last << section
38
+ stack << section
39
+ success = true
40
+ else
41
+ stack.pop
42
+ end
43
+ end
44
+ end
45
+ sections
46
+ end
47
+
48
+ # Create nested fragment nodes under +parent+ from +sections+ (which can be created using
49
+ # +parse_html_headers+). +path+ is the source path that defines the fragments. The meta
50
+ # information +in_menu+ of the fragment nodes is set to the parameter +in_menu+ and the meta
51
+ # info +sort_info+ is calculated from the base +si+ value.
52
+ def create_fragment_nodes(sections, parent, path, in_menu, si = 1000 )
53
+ sections.each do |level, id, title, sub_sections|
54
+ node = website.blackboard.invoke(:create_nodes, parent.tree, parent.absolute_lcn,
55
+ Webgen::Path.new('#' + id, path.source_path),
56
+ self) do |cn_parent, cn_path|
57
+ cn_path.meta_info['title'] = title
58
+ cn_path.meta_info['in_menu'] = in_menu
59
+ cn_path.meta_info['sort_info'] = si = si.succ
60
+ create_node(cn_parent, cn_path)
61
+ end.first
62
+ create_fragment_nodes(sub_sections, node, path, in_menu, si.succ)
63
+ end
64
+ end
65
+
66
+ end
67
+
68
+ end