gettalong-webgen 0.5.4.20080929

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (290) hide show
  1. data/AUTHORS +5 -0
  2. data/COPYING +10 -0
  3. data/GPL +340 -0
  4. data/Rakefile +324 -0
  5. data/THANKS +17 -0
  6. data/bin/webgen +10 -0
  7. data/data/webgen/resources.yaml +3 -0
  8. data/data/webgen/webgui/controller/main.rb +129 -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 +6 -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 +61 -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 +66 -0
  117. data/doc/contentprocessor/builder.page +80 -0
  118. data/doc/contentprocessor/erb.page +56 -0
  119. data/doc/contentprocessor/erubis.page +46 -0
  120. data/doc/contentprocessor/haml.page +47 -0
  121. data/doc/contentprocessor/maruku.page +41 -0
  122. data/doc/contentprocessor/rdiscount.page +37 -0
  123. data/doc/contentprocessor/rdoc.page +36 -0
  124. data/doc/contentprocessor/redcloth.page +39 -0
  125. data/doc/contentprocessor/sass.page +31 -0
  126. data/doc/contentprocessor/tags.page +73 -0
  127. data/doc/extensions.metainfo +29 -0
  128. data/doc/extensions.page +16 -0
  129. data/doc/extensions.template +17 -0
  130. data/doc/faq.page +214 -0
  131. data/doc/getting_started.page +134 -0
  132. data/doc/index.page +65 -0
  133. data/doc/manual.page +532 -0
  134. data/doc/reference_configuration.page +646 -0
  135. data/doc/reference_metainfo.page +213 -0
  136. data/doc/sourcehandler.template +21 -0
  137. data/doc/sourcehandler/copy.page +19 -0
  138. data/doc/sourcehandler/directory.page +27 -0
  139. data/doc/sourcehandler/feed.page +82 -0
  140. data/doc/sourcehandler/metainfo.page +41 -0
  141. data/doc/sourcehandler/page.page +30 -0
  142. data/doc/sourcehandler/sitemap.page +46 -0
  143. data/doc/sourcehandler/template.page +45 -0
  144. data/doc/sourcehandler/virtual.page +49 -0
  145. data/doc/tag.template +25 -0
  146. data/doc/tag/breadcrumbtrail.page +40 -0
  147. data/doc/tag/coderay.page +49 -0
  148. data/doc/tag/date.page +31 -0
  149. data/doc/tag/executecommand.page +26 -0
  150. data/doc/tag/includefile.page +32 -0
  151. data/doc/tag/langbar.page +22 -0
  152. data/doc/tag/menu.page +92 -0
  153. data/doc/tag/metainfo.page +29 -0
  154. data/doc/tag/relocatable.page +38 -0
  155. data/doc/tag/sitemap.page +31 -0
  156. data/doc/upgrading.page +139 -0
  157. data/doc/webgen_page_format.page +128 -0
  158. data/lib/webgen/blackboard.rb +73 -0
  159. data/lib/webgen/cache.rb +85 -0
  160. data/lib/webgen/cli.rb +118 -0
  161. data/lib/webgen/cli/create_command.rb +64 -0
  162. data/lib/webgen/cli/run_command.rb +20 -0
  163. data/lib/webgen/cli/utils.rb +86 -0
  164. data/lib/webgen/cli/webgui_command.rb +49 -0
  165. data/lib/webgen/common.rb +10 -0
  166. data/lib/webgen/common/sitemap.rb +76 -0
  167. data/lib/webgen/configuration.rb +147 -0
  168. data/lib/webgen/contentprocessor.rb +96 -0
  169. data/lib/webgen/contentprocessor/blocks.rb +46 -0
  170. data/lib/webgen/contentprocessor/builder.rb +26 -0
  171. data/lib/webgen/contentprocessor/context.rb +90 -0
  172. data/lib/webgen/contentprocessor/erb.rb +24 -0
  173. data/lib/webgen/contentprocessor/erubis.rb +40 -0
  174. data/lib/webgen/contentprocessor/haml.rb +25 -0
  175. data/lib/webgen/contentprocessor/maruku.rb +18 -0
  176. data/lib/webgen/contentprocessor/rdiscount.rb +15 -0
  177. data/lib/webgen/contentprocessor/rdoc.rb +17 -0
  178. data/lib/webgen/contentprocessor/redcloth.rb +15 -0
  179. data/lib/webgen/contentprocessor/sass.rb +18 -0
  180. data/lib/webgen/contentprocessor/tags.rb +134 -0
  181. data/lib/webgen/coreext.rb +10 -0
  182. data/lib/webgen/default_config.rb +198 -0
  183. data/lib/webgen/languages.rb +578 -0
  184. data/lib/webgen/loggable.rb +23 -0
  185. data/lib/webgen/logger.rb +78 -0
  186. data/lib/webgen/node.rb +347 -0
  187. data/lib/webgen/output.rb +37 -0
  188. data/lib/webgen/output/filesystem.rb +67 -0
  189. data/lib/webgen/page.rb +133 -0
  190. data/lib/webgen/path.rb +182 -0
  191. data/lib/webgen/source.rb +24 -0
  192. data/lib/webgen/source/filesystem.rb +58 -0
  193. data/lib/webgen/source/resource.rb +42 -0
  194. data/lib/webgen/source/stacked.rb +53 -0
  195. data/lib/webgen/sourcehandler.rb +202 -0
  196. data/lib/webgen/sourcehandler/base.rb +211 -0
  197. data/lib/webgen/sourcehandler/copy.rb +41 -0
  198. data/lib/webgen/sourcehandler/directory.rb +31 -0
  199. data/lib/webgen/sourcehandler/feed.rb +121 -0
  200. data/lib/webgen/sourcehandler/fragment.rb +71 -0
  201. data/lib/webgen/sourcehandler/metainfo.rb +117 -0
  202. data/lib/webgen/sourcehandler/page.rb +77 -0
  203. data/lib/webgen/sourcehandler/sitemap.rb +60 -0
  204. data/lib/webgen/sourcehandler/template.rb +68 -0
  205. data/lib/webgen/sourcehandler/virtual.rb +75 -0
  206. data/lib/webgen/tag.rb +23 -0
  207. data/lib/webgen/tag/base.rb +162 -0
  208. data/lib/webgen/tag/breadcrumbtrail.rb +71 -0
  209. data/lib/webgen/tag/coderay.rb +32 -0
  210. data/lib/webgen/tag/date.rb +18 -0
  211. data/lib/webgen/tag/executecommand.rb +29 -0
  212. data/lib/webgen/tag/includefile.rb +42 -0
  213. data/lib/webgen/tag/langbar.rb +52 -0
  214. data/lib/webgen/tag/menu.rb +186 -0
  215. data/lib/webgen/tag/metainfo.rb +25 -0
  216. data/lib/webgen/tag/relocatable.rb +53 -0
  217. data/lib/webgen/tag/sitemap.rb +42 -0
  218. data/lib/webgen/tree.rb +80 -0
  219. data/lib/webgen/version.rb +6 -0
  220. data/lib/webgen/webgentask.rb +148 -0
  221. data/lib/webgen/website.rb +214 -0
  222. data/lib/webgen/websiteaccess.rb +29 -0
  223. data/lib/webgen/websitemanager.rb +125 -0
  224. data/man/man1/webgen.1 +67 -0
  225. data/misc/default.css +360 -0
  226. data/misc/default.template +75 -0
  227. data/misc/htmldoc.metainfo +25 -0
  228. data/misc/htmldoc.virtual +5 -0
  229. data/misc/images/arrow.gif +0 -0
  230. data/misc/images/error.gif +0 -0
  231. data/misc/images/exclamation.gif +0 -0
  232. data/misc/images/headerbg.jpg +0 -0
  233. data/misc/images/information.gif +0 -0
  234. data/misc/images/quote.gif +0 -0
  235. data/setup.rb +1585 -0
  236. data/test/helper.rb +41 -0
  237. data/test/test_blackboard.rb +58 -0
  238. data/test/test_cache.rb +57 -0
  239. data/test/test_common_sitemap.rb +56 -0
  240. data/test/test_configuration.rb +66 -0
  241. data/test/test_contentprocessor.rb +31 -0
  242. data/test/test_contentprocessor_blocks.rb +34 -0
  243. data/test/test_contentprocessor_builder.rb +19 -0
  244. data/test/test_contentprocessor_context.rb +38 -0
  245. data/test/test_contentprocessor_erb.rb +20 -0
  246. data/test/test_contentprocessor_erubis.rb +47 -0
  247. data/test/test_contentprocessor_haml.rb +20 -0
  248. data/test/test_contentprocessor_maruku.rb +27 -0
  249. data/test/test_contentprocessor_rdiscount.rb +15 -0
  250. data/test/test_contentprocessor_rdoc.rb +16 -0
  251. data/test/test_contentprocessor_redcloth.rb +12 -0
  252. data/test/test_contentprocessor_sass.rb +20 -0
  253. data/test/test_contentprocessor_tags.rb +97 -0
  254. data/test/test_languages.rb +53 -0
  255. data/test/test_loggable.rb +30 -0
  256. data/test/test_logger.rb +73 -0
  257. data/test/test_node.rb +339 -0
  258. data/test/test_output_filesystem.rb +58 -0
  259. data/test/test_page.rb +203 -0
  260. data/test/test_path.rb +131 -0
  261. data/test/test_source_filesystem.rb +59 -0
  262. data/test/test_source_resource.rb +26 -0
  263. data/test/test_source_stacked.rb +34 -0
  264. data/test/test_sourcehandler_base.rb +92 -0
  265. data/test/test_sourcehandler_copy.rb +45 -0
  266. data/test/test_sourcehandler_directory.rb +25 -0
  267. data/test/test_sourcehandler_feed.rb +74 -0
  268. data/test/test_sourcehandler_fragment.rb +67 -0
  269. data/test/test_sourcehandler_metainfo.rb +93 -0
  270. data/test/test_sourcehandler_page.rb +70 -0
  271. data/test/test_sourcehandler_sitemap.rb +47 -0
  272. data/test/test_sourcehandler_template.rb +63 -0
  273. data/test/test_sourcehandler_virtual.rb +56 -0
  274. data/test/test_tag_base.rb +82 -0
  275. data/test/test_tag_breadcrumbtrail.rb +89 -0
  276. data/test/test_tag_coderay.rb +30 -0
  277. data/test/test_tag_date.rb +16 -0
  278. data/test/test_tag_executecommand.rb +39 -0
  279. data/test/test_tag_includefile.rb +48 -0
  280. data/test/test_tag_langbar.rb +60 -0
  281. data/test/test_tag_menu.rb +195 -0
  282. data/test/test_tag_metainfo.rb +17 -0
  283. data/test/test_tag_relocatable.rb +57 -0
  284. data/test/test_tag_sitemap.rb +44 -0
  285. data/test/test_tree.rb +69 -0
  286. data/test/test_webgentask.rb +21 -0
  287. data/test/test_website.rb +96 -0
  288. data/test/test_websiteaccess.rb +23 -0
  289. data/test/test_websitemanager.rb +68 -0
  290. metadata +575 -0
@@ -0,0 +1,41 @@
1
+ module Webgen::SourceHandler
2
+
3
+ # Simple source handler for copying files from the source tree, either verbatim or by applying a
4
+ # content processor.
5
+ class Copy
6
+
7
+ include Webgen::WebsiteAccess
8
+ include Base
9
+
10
+ # Create the node for +parent+ and +path+. If the +path+ has the name of a content processor in
11
+ # the extension, it is preprocessed.
12
+ def create_node(parent, path)
13
+ if path.ext.index('.')
14
+ processor, *rest = path.ext.split('.')
15
+ if website.blackboard.invoke(:content_processor_names).include?(processor)
16
+ path.ext = rest.join('.')
17
+ else
18
+ processor = nil
19
+ end
20
+ end
21
+ super(parent, path) do |node|
22
+ node.node_info[:preprocessor] = processor
23
+ end
24
+ end
25
+
26
+ # Return either the preprocessed content of the +node+ or the IO object for the node's source
27
+ # path depending on the node type.
28
+ def content(node)
29
+ io = website.blackboard.invoke(:source_paths)[node.node_info[:src]].io
30
+ if node.node_info[:preprocessor]
31
+ context = Webgen::ContentProcessor::Context.new(:content => io.data, :chain => [node])
32
+ website.blackboard.invoke(:content_processor, node.node_info[:preprocessor]).call(context)
33
+ context.content
34
+ else
35
+ io
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,31 @@
1
+ require 'webgen/sourcehandler/base'
2
+
3
+ module Webgen::SourceHandler
4
+
5
+ # Handles directory source paths.
6
+ class Directory
7
+
8
+ include Base
9
+
10
+ # Creation of directory nodes is special because once they are created, they are only deleted
11
+ # when the source path gets deleted. Otherwise, only the meta information of the node gets
12
+ # updated.
13
+ def create_node(parent, path)
14
+ if node = node_exists?(parent, path)
15
+ node.meta_info.clear
16
+ node.meta_info.update(path.meta_info)
17
+ node.dirty = true
18
+ node
19
+ else
20
+ super(parent, path)
21
+ end
22
+ end
23
+
24
+ # Return an empty string to signal that the directory should be written to the output.
25
+ def content(node)
26
+ ''
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,121 @@
1
+ require 'webgen/websiteaccess'
2
+ require 'webgen/sourcehandler/base'
3
+
4
+ module Webgen::SourceHandler
5
+
6
+ # Source handler for creating atom and/or rss feeds.
7
+ class Feed
8
+
9
+ include Webgen::WebsiteAccess
10
+ include Base
11
+
12
+ # The mandatory keys that need to be set in a feed file.
13
+ MANDATORY_INFOS = %W[site_url author entries]
14
+
15
+ def initialize # :nodoc:
16
+ website.blackboard.add_listener(:node_changed?, method(:node_changed?))
17
+ end
18
+
19
+ # Create atom and/or rss feed files from +parent+ and +path+.
20
+ def create_node(parent, path)
21
+ page = page_from_path(path)
22
+ path.meta_info['link'] ||= parent.absolute_lcn
23
+
24
+ if MANDATORY_INFOS.any? {|t| path.meta_info[t].nil?}
25
+ raise "One of #{MANDATORY_INFOS.join('/')} information missing for feed <#{path}>"
26
+ end
27
+
28
+ create_feed_node = lambda do |type|
29
+ path.ext = type
30
+ super(parent, path) do |node|
31
+ node.node_info[:feed] = page
32
+ node.node_info[:feed_type] = type
33
+ end
34
+ end
35
+
36
+ nodes = []
37
+ nodes << create_feed_node['atom'] if path.meta_info['atom']
38
+ nodes << create_feed_node['rss'] if path.meta_info['rss']
39
+
40
+ nodes
41
+ end
42
+
43
+ # Return the rendered feed represented by +node+.
44
+ def content(node)
45
+ website.cache[[:sourcehandler_feed, node.node_info[:src]]] = feed_entries(node).map {|n| n.absolute_lcn}
46
+ block_name = node.node_info[:feed_type] + '_template'
47
+ if node.node_info[:feed].blocks.has_key?(block_name)
48
+ node.node_info[:feed].blocks[block_name].
49
+ render(Webgen::ContentProcessor::Context.new(:chain => [node])).content
50
+ else
51
+ feed = (website.cache.volatile[:sourcehandler_feed] ||= {})[node.node_info[:src]] ||= build_feed_for(node)
52
+ feed.feed_type = node.node_info[:feed_type]
53
+ feed.build_xml
54
+ end
55
+ end
56
+
57
+ # Helper method for returning the entries for the feed node +node+.
58
+ def feed_entries(node)
59
+ nr_items = (node['number_of_entries'].to_i == 0 ? 10 : node['number_of_entries'].to_i)
60
+ patterns = [node['entries']].flatten.map {|pat| Pathname.new(pat =~ /^\// ? pat : File.join(node.parent.absolute_lcn, pat)).cleanpath.to_s}
61
+
62
+ node.tree.node_access[:alcn].values.
63
+ select {|node| patterns.any? {|pat| node =~ pat} && node.node_info[:page]}.
64
+ sort {|a,b| a['modified_at'] <=> b['modified_at']}.
65
+ reverse[0, nr_items]
66
+ end
67
+
68
+ #######
69
+ private
70
+ #######
71
+
72
+ # Return the populated FeedTools::Feed object for +node+.
73
+ def build_feed_for(node)
74
+ require 'feed_tools'
75
+ require 'time'
76
+
77
+ site_url = node['site_url']
78
+
79
+ feed = FeedTools::Feed.new
80
+ feed.title = node['title']
81
+ feed.description = node['description']
82
+ feed.author = node['author']
83
+ feed.author.url = node['author_url']
84
+ feed.base_uri = site_url
85
+ feed.link = File.join(site_url, node.tree[node['link']].path)
86
+ feed.id = feed.link
87
+
88
+ feed.published = (node['created_at'].kind_of?(Time) ? node['created_at'] : Time.now)
89
+ feed.updated = Time.now
90
+ feed.generator = 'webgen - Webgen::SourceHandler::Feed'
91
+ feed.icon = File.join(site_url, node.tree[node['icon']].path) if node['icon']
92
+
93
+ node.feed_entries.each do |entry|
94
+ item = FeedTools::FeedItem.new
95
+ item.title = entry['title']
96
+ item.link = File.join(site_url, entry.path)
97
+ item.content = entry.node_info[:page].blocks['content'].render(Webgen::ContentProcessor::Context.new(:chain => [entry])).content
98
+ item.updated = entry['modified_at']
99
+ item.published = entry['created_at'] if entry['created_at'].kind_of?(Time)
100
+ if entry['author']
101
+ item.author = entry['author']
102
+ item.author.url = entry['author_url']
103
+ end
104
+ item.id = item.link
105
+ feed << item
106
+ end
107
+ feed
108
+ end
109
+
110
+ # Check if the +node+ has meta information from any meta info node and if so, if the meta info
111
+ # node in question has changed.
112
+ def node_changed?(node)
113
+ return if node.node_info[:processor] != self.class.name
114
+ entries = node.feed_entries
115
+ node.dirty = true if entries.map {|n| n.absolute_lcn } != website.cache[[:sourcehandler_feed, node.node_info[:src]]] ||
116
+ entries.any? {|n| n.changed?}
117
+ end
118
+
119
+ end
120
+
121
+ end
@@ -0,0 +1,71 @@
1
+ require 'webgen/sourcehandler/base'
2
+ require 'webgen/websiteaccess'
3
+
4
+ module Webgen::SourceHandler
5
+
6
+ # Handles page fragment nodes and provides utility methods for parsing HTML headers and generating
7
+ # fragment nodes from them.
8
+ class Fragment
9
+
10
+ include Base
11
+ include Webgen::WebsiteAccess
12
+
13
+ HTML_HEADER_REGEXP = /<h([123456])(?:>|\s([^>]*)>)(.*?)<\/h\1\s*>/i
14
+ HTML_ATTR_REGEXP = /\s*(\w+)\s*=\s*('|")([^\2]+)\2\s*/
15
+
16
+ # Parse the string +content+ for headers +h1+, ..., +h6+ and return the found, nested sections.
17
+ #
18
+ # Only those headers are used which have an +id+ attribute set. The method returns a list of
19
+ # arrays with entries <tt>level, id, title, sub sections</tt> where <tt>sub sections</tt> is
20
+ # such a list again.
21
+ def parse_html_headers(content)
22
+ sections = []
23
+ stack = []
24
+ content.scan(HTML_HEADER_REGEXP).each do |level,attrs,title|
25
+ next if attrs.nil?
26
+ id_attr = attrs.scan(HTML_ATTR_REGEXP).find {|name,sep,value| name == 'id'}
27
+ next if id_attr.nil?
28
+ id = id_attr[2]
29
+
30
+ section = [level.to_i, id, title, []]
31
+ success = false
32
+ while !success
33
+ if stack.empty?
34
+ sections << section
35
+ stack << section
36
+ success = true
37
+ elsif stack.last.first < section.first
38
+ stack.last.last << section
39
+ stack << section
40
+ success = true
41
+ else
42
+ stack.pop
43
+ end
44
+ end
45
+ end
46
+ sections
47
+ end
48
+
49
+ # Create nested fragment nodes under +parent+ from +sections+ (which can be created using
50
+ # +parse_html_headers+). +path+ is the source path that defines the fragments. The meta
51
+ # information +in_menu+ of the fragment nodes is set to the parameter +in_menu+ and the meta
52
+ # info +sort_info+ is calculated from the base +si+ value.
53
+ def create_fragment_nodes(sections, parent, path, in_menu, si = 1000 )
54
+ sections.each do |level, id, title, sub_sections|
55
+ node = website.blackboard.invoke(:create_nodes, parent.tree, parent.absolute_lcn,
56
+ path, self) do |cn_parent, cn_path|
57
+ ptemp = Webgen::Path.new('#' + id)
58
+ ptemp.meta_info = cn_path.meta_info.merge(ptemp.meta_info)
59
+ create_node(cn_parent, ptemp)
60
+ end.first
61
+ node['title'] = title
62
+ node['in_menu'] = in_menu
63
+ node['sort_info'] = si = si.succ
64
+ node.node_info[:src] = path.path
65
+ create_fragment_nodes(sub_sections, node, path, in_menu, si.succ)
66
+ end
67
+ end
68
+
69
+ end
70
+
71
+ end
@@ -0,0 +1,117 @@
1
+ require 'pathname'
2
+ require 'yaml'
3
+ require 'webgen/sourcehandler/base'
4
+ require 'webgen/websiteaccess'
5
+
6
+ module Webgen::SourceHandler
7
+
8
+ # Handles meta information files which provide meta information for other files.
9
+ class Metainfo
10
+
11
+ include Base
12
+ include Webgen::WebsiteAccess
13
+
14
+ CKEY = [:metainfo, :nodes]
15
+
16
+ # Upon creation the object registers itself as listener for some node hooks.
17
+ def initialize
18
+ website.blackboard.add_listener(:node_meta_info_changed?, method(:node_meta_info_changed?))
19
+ website.blackboard.add_listener(:before_node_created, method(:before_node_created))
20
+ website.blackboard.add_listener(:before_node_deleted, method(:before_node_deleted))
21
+ website.blackboard.add_listener(:after_node_created, method(:after_node_created))
22
+ self.nodes ||= Set.new
23
+ end
24
+
25
+ # Create a meta info node from +parent+ and +path+.
26
+ def create_node(parent, path)
27
+ page = page_from_path(path)
28
+ super(parent, path) do |node|
29
+ [[:mi_paths, 'paths'], [:mi_alcn, 'alcn']].each do |mi_key, block_name|
30
+ node.node_info[mi_key] = {}
31
+ YAML::load(page.blocks[block_name].content).each do |key, value|
32
+ key = Pathname.new(key =~ /^\// ? key : File.join(parent.absolute_lcn, key)).cleanpath.to_s
33
+ key.chomp('/') unless key == '/'
34
+ node.node_info[mi_key][key] = value
35
+ end if page.blocks.has_key?(block_name)
36
+ end
37
+ website.cache[[:sh_metainfo_node_mi, node.absolute_lcn]] = {
38
+ :mi_paths => node.node_info[:mi_paths],
39
+ :mi_alcn => node.node_info[:mi_alcn]
40
+ }
41
+
42
+ mark_all_matched_dirty(node)
43
+
44
+ self.nodes << node
45
+ self.nodes = self.nodes.sort_by {|n| n.absolute_lcn}
46
+ end
47
+ end
48
+
49
+ def nodes #:nodoc:
50
+ website.cache.permanent[CKEY]
51
+ end
52
+
53
+ def nodes=(val) #:nodoc:
54
+ website.cache.permanent[CKEY] = val
55
+ end
56
+
57
+ #######
58
+ private
59
+ #######
60
+
61
+ # Return +true+ if any meta information for +node+ provided by +mi_node+ has changed.
62
+ def meta_info_changed?(mi_node, node, use_cache = true)
63
+ use_cache = false if !website.cache.old_data[[:sh_metainfo_node_mi, mi_node.absolute_lcn]]
64
+ cached = website.cache[[:sh_metainfo_node_mi, mi_node.absolute_lcn]]
65
+ path = website.blackboard.invoke(:source_paths)[node.node_info[:src]]
66
+ (mi_node.node_info[:mi_paths].any? {|pattern, mi| path =~ pattern && (!use_cache || mi != cached[:mi_paths][pattern])} ||
67
+ mi_node.node_info[:mi_alcn].any? {|pattern, mi| node =~ pattern && (!use_cache || mi != cached[:mi_alcn][pattern])})
68
+ end
69
+
70
+ # Mark all nodes that are matched by a path or an alcn specifcation in the meta info node +node+
71
+ # as dirty.
72
+ def mark_all_matched_dirty(node, use_cache = true)
73
+ node.tree.node_access[:alcn].each do |path, n|
74
+ n.dirty_meta_info = true if meta_info_changed?(node, n, use_cache)
75
+ end
76
+ end
77
+
78
+ # Update the meta info of matched path before a node is created.
79
+ def before_node_created(parent, path)
80
+ self.nodes.each do |node|
81
+ node.node_info[:mi_paths].each do |pattern, mi|
82
+ path.meta_info.update(mi) if path =~ pattern
83
+ end
84
+ end
85
+ end
86
+
87
+ # Update the meta information of a matched alcn after the node has been created.
88
+ def after_node_created(node)
89
+ self.nodes.each do |n|
90
+ n.node_info[:mi_alcn].each do |pattern, mi|
91
+ node.meta_info.update(mi) if node =~ pattern
92
+ end
93
+ end
94
+ end
95
+
96
+ # Check if the +node+ has meta information from any meta info node and if so, if the meta info
97
+ # node in question has changed.
98
+ def node_meta_info_changed?(node)
99
+ return if self.nodes.include?(node)
100
+ self.nodes.each do |n|
101
+ if n.created && meta_info_changed?(n, node)
102
+ node.dirty_meta_info = true
103
+ return
104
+ end
105
+ end
106
+ end
107
+
108
+ # Delete the meta info node +node+ from the internal array.
109
+ def before_node_deleted(node)
110
+ return unless node.node_info[:processor] == self.class.name
111
+ mark_all_matched_dirty(node, false) if !website.blackboard.invoke(:source_paths).include?(node.node_info[:src])
112
+ self.nodes.delete(node)
113
+ end
114
+
115
+ end
116
+
117
+ end
@@ -0,0 +1,77 @@
1
+ require 'webgen/websiteaccess'
2
+ require 'webgen/sourcehandler/base'
3
+
4
+ module Webgen::SourceHandler
5
+
6
+ # Source handler for handling content files in Webgen Page Format.
7
+ class Page
8
+
9
+ include Webgen::WebsiteAccess
10
+ include Base
11
+
12
+ def initialize #:nodoc:
13
+ website.blackboard.add_listener(:node_meta_info_changed?, method(:meta_info_changed?))
14
+ end
15
+
16
+ # Create a page file from +parent+ and +path+.
17
+ def create_node(parent, path)
18
+ page = page_from_path(path)
19
+ path.meta_info['lang'] ||= website.config['website.lang']
20
+ path.ext = 'html' if path.ext == 'page'
21
+
22
+ super(parent, path) do |node|
23
+ website.cache[[:sh_page_node_mi, node.absolute_lcn]] = node.meta_info.dup
24
+
25
+ node.node_info[:page] = page
26
+ tmp_logger = website.logger
27
+ website.logger = nil # disabling logging whiling creating fragment nodes
28
+
29
+ website.cache.permanent[:page_sections] ||= {}
30
+ sections = if path.changed? || !website.cache.permanent[:page_sections][node.absolute_lcn]
31
+ website.blackboard.invoke(:parse_html_headers, render_node(node, 'content', []))
32
+ else
33
+ website.cache.permanent[:page_sections][node.absolute_lcn]
34
+ end
35
+ website.cache.permanent[:page_sections][node.absolute_lcn] = sections
36
+ website.blackboard.invoke(:create_fragment_nodes,
37
+ sections,
38
+ node, website.blackboard.invoke(:source_paths)[path.path],
39
+ node.meta_info['fragments_in_menu'])
40
+ website.logger = tmp_logger
41
+ end
42
+ end
43
+
44
+ # Render the block called +block_name+ of the given +node+. The parameter +templates+ is set to
45
+ # the default template chain for the given +node+ but you can assign a custom template chain (an
46
+ # array of template nodes) if need arises. Return +nil+ if an error occurred.
47
+ def render_node(node, block_name = 'content', templates = website.blackboard.invoke(:templates_for_node, node))
48
+ chain = [templates, node].flatten
49
+
50
+ if chain.first.node_info[:page].blocks.has_key?(block_name)
51
+ node.node_info[:used_nodes] << chain.first.absolute_lcn
52
+ context = chain.first.node_info[:page].blocks[block_name].render(Webgen::ContentProcessor::Context.new(:chain => chain))
53
+ context.content
54
+ else
55
+ raise "Error rendering <#{node.absolute_lcn}>: no block named '#{block_name}' in <#{chain.first.absolute_lcn}>"
56
+ end
57
+ end
58
+ alias_method :content, :render_node
59
+
60
+ #######
61
+ private
62
+ #######
63
+
64
+ # Checks if the meta information provided by the file in Webgen Page Format changed.
65
+ def meta_info_changed?(node)
66
+ return if !node.created || node.node_info[:processor] != self.class.name
67
+ ckey = [:sh_page_node_mi, node.absolute_lcn]
68
+ old_mi = website.cache.old_data[ckey]
69
+ old_mi.delete('modified_at') if old_mi
70
+ new_mi = website.cache.new_data[ckey]
71
+ new_mi.delete('modified_at')
72
+ node.dirty_meta_info = true if old_mi != new_mi
73
+ end
74
+
75
+ end
76
+
77
+ end