thewoolleyman-webgen 0.5.8.20090419

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 (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,54 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Webgen
4
+
5
+ # Namespace for all classes that provide source paths.
6
+ #
7
+ # == Implementing a source class
8
+ #
9
+ # Source classes provide access to the source paths on which the source handlers act.
10
+ #
11
+ # A source class only needs to respond to the method +paths+ which needs to return a set of paths
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). 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]
43
+ #
44
+ module Source
45
+
46
+ autoload :Base, 'webgen/source/base'
47
+ autoload :FileSystem, 'webgen/source/filesystem'
48
+ autoload :Stacked, 'webgen/source/stacked'
49
+ autoload :Resource, 'webgen/source/resource'
50
+ autoload :TarArchive, 'webgen/source/tararchive'
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,61 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'pathname'
4
+ require 'webgen/websiteaccess'
5
+ require 'webgen/path'
6
+
7
+ module Webgen
8
+
9
+ # This class is used to read source paths from a directory in the file system.
10
+ class Source::FileSystem
11
+
12
+ # A special Webgen::Path class for handling with file system paths.
13
+ class Path < Webgen::Path
14
+
15
+ # Create a new object with absolute path +path+ for the file system path +fs_path+.
16
+ def initialize(path, fs_path)
17
+ super(path) { File.open(fs_path, 'rb') }
18
+ @fs_path = fs_path
19
+ WebsiteAccess.website.cache[[:fs_path, @fs_path]] = File.mtime(@fs_path)
20
+ @meta_info['modified_at'] = File.mtime(@fs_path)
21
+ end
22
+
23
+ # Return +true+ if the file system path used by the object has been modified.
24
+ def changed?
25
+ data = WebsiteAccess.website.cache[[:fs_path, @fs_path]]
26
+ File.mtime(@fs_path) > data
27
+ end
28
+
29
+ end
30
+
31
+ # The root path from which paths read.
32
+ attr_reader :root
33
+
34
+ # The glob (see Dir.glob for details) that is used to specify which paths under the root path
35
+ # should be returned by #paths.
36
+ attr_reader :glob
37
+
38
+ # Create a new file system source for the root path +root+ using the provided +glob+.
39
+ def initialize(root, glob = '**/*')
40
+ if root =~ /^([a-zA-Z]:|\/)/
41
+ @root = root
42
+ else
43
+ @root = File.join(WebsiteAccess.website.directory, root)
44
+ end
45
+ @glob = glob
46
+ end
47
+
48
+ # Return all paths under #root which match #glob.
49
+ def paths
50
+ @paths ||= Dir.glob(File.join(@root, @glob), File::FNM_DOTMATCH|File::FNM_CASEFOLD).to_set.collect do |f|
51
+ next unless File.exists?(f) # handle invalid links
52
+ temp = Pathname.new(f.sub(/^#{Regexp.escape(@root)}\/?/, '/')).cleanpath.to_s
53
+ temp += '/' if File.directory?(f) && temp[-1] != ?/
54
+ path = Path.new(temp, f)
55
+ path
56
+ end.compact
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,44 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'webgen/websiteaccess'
4
+ require 'webgen/source'
5
+
6
+ module Webgen::Source
7
+
8
+ # This class is used to provide access to sources provided by resources.
9
+ class Resource
10
+
11
+ include Webgen::WebsiteAccess
12
+
13
+ # The glob (see File.fnmatch) specifying the resources.
14
+ attr_reader :glob
15
+
16
+ # The glob (see File.fnmatch) specifying the paths that should be used from the resources.
17
+ attr_reader :paths_glob
18
+
19
+ # The prefix that should optionally be stripped from the paths.
20
+ attr_reader :strip_prefix
21
+
22
+ # Create a new resource source for the the +glob+ and use only those paths matching +paths_glob+
23
+ # while stripping +strip_prefix+ off the path.
24
+ def initialize(glob, paths_glob = nil, strip_prefix = nil)
25
+ @glob, @paths_glob, @strip_prefix = glob, paths_glob, strip_prefix
26
+ end
27
+
28
+ # Return all paths associated with the resources identified by #glob.
29
+ def paths
30
+ if !defined?(@paths)
31
+ stack = Stacked.new
32
+ website.config['resources'].select {|name, infos| File.fnmatch(@glob, name)}.sort.each do |name, infos|
33
+ stack.add([['/', constant(infos.first).new(*infos[1..-1])]])
34
+ end
35
+ @paths = stack.paths
36
+ @paths = @paths.select {|p| File.fnmatch(@paths_glob, p)} if @paths_glob
37
+ @paths.collect! {|p| p.mount_at('/', @strip_prefix)} if @strip_prefix
38
+ end
39
+ @paths
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,55 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Webgen::Source
4
+
5
+ # This source class is used to stack several sources together.
6
+ #
7
+ # It serves two purposes:
8
+ #
9
+ # * First, it can be used to access more than one source. This is useful when your website
10
+ # consists of more than one source directory and you want to use all of them.
11
+ #
12
+ # * Second, sources can be mounted on specific directories. For example, a folder with images that
13
+ # you don't want to copy to the website source directory can be mounted under <tt>/images</tt>
14
+ # sothat they are available nonetheless.
15
+ #
16
+ # Also be aware that when a path is returned by a source that has already be returned by a prior
17
+ # source, it is discarded and not used.
18
+ class Stacked
19
+
20
+ # Return the stack of Webgen::Source objects.
21
+ attr_reader :stack
22
+
23
+ # Create a new stack. The optional +map+ parameter can be used to provide initial mappings of
24
+ # mount points to source objects (see #add for details).
25
+ def initialize(map = {})
26
+ @stack = []
27
+ add(map)
28
+ end
29
+
30
+ # Add all mappings found in +maps+ to the stack. The parameter +maps+ should be an array of
31
+ # two-element arrays which contain an absolute directoriy (ie. starting with a slash) and a
32
+ # source object.
33
+ def add(maps)
34
+ maps.each do |mp, source|
35
+ raise "Invalid mount point specified: #{mp}" unless mp =~ /^\//
36
+ @stack << [mp, source]
37
+ end
38
+ end
39
+
40
+ # Return all paths returned by the sources in the stack. Since the stack is ordered, paths
41
+ # returned by later source objects are not used if a prior source object has returned the same
42
+ # path.
43
+ def paths
44
+ @paths = Set.new
45
+ @stack.each do |mp, source|
46
+ source.paths.each do |path|
47
+ @paths.add?(path.mount_at(mp))
48
+ end
49
+ end
50
+ @paths
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -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
@@ -0,0 +1,226 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'webgen/loggable'
4
+ require 'benchmark'
5
+
6
+ module Webgen
7
+
8
+ # Namespace for all classes that handle source paths.
9
+ #
10
+ # Have a look at Webgen::SourceHandler::Base for details on how to implement a source handler
11
+ # class.
12
+ module SourceHandler
13
+
14
+ autoload :Base, 'webgen/sourcehandler/base'
15
+ autoload :Copy, 'webgen/sourcehandler/copy'
16
+ autoload :Directory, 'webgen/sourcehandler/directory'
17
+ autoload :Metainfo, 'webgen/sourcehandler/metainfo'
18
+ autoload :Template, 'webgen/sourcehandler/template'
19
+ autoload :Page, 'webgen/sourcehandler/page'
20
+ autoload :Fragment, 'webgen/sourcehandler/fragment'
21
+ autoload :Virtual, 'webgen/sourcehandler/virtual'
22
+ autoload :Feed, 'webgen/sourcehandler/feed'
23
+ autoload :Sitemap, 'webgen/sourcehandler/sitemap'
24
+ autoload :Memory, 'webgen/sourcehandler/memory'
25
+
26
+ # This class is used by Website to do the actual rendering of the website. It
27
+ #
28
+ # * collects all source paths using the source classes
29
+ # * creates nodes using the source handler classes
30
+ # * writes changed nodes out using an output class
31
+ class Main
32
+
33
+ include WebsiteAccess
34
+ include Loggable
35
+
36
+ def initialize #:nodoc:
37
+ website.blackboard.add_service(:create_nodes, method(:create_nodes))
38
+ website.blackboard.add_service(:source_paths, method(:find_all_source_paths))
39
+ website.blackboard.add_listener(:node_meta_info_changed?, method(:meta_info_changed?))
40
+ end
41
+
42
+ # Render the nodes provided in the +tree+. Before the actual rendering is done, the sources
43
+ # are checked (nodes for deleted sources are deleted, nodes for new and changed sources).
44
+ def render(tree)
45
+ begin
46
+ website.logger.mark_new_cycle if website.logger
47
+
48
+ puts "Updating tree..."
49
+ time = Benchmark.measure do
50
+ website.cache.reset_volatile_cache
51
+ update_tree(tree)
52
+ end
53
+ puts "...done in " + ('%2.4f' % time.real) + ' seconds'
54
+
55
+ if !tree.root
56
+ puts 'No source files found - maybe not a webgen website?'
57
+ return nil
58
+ end
59
+
60
+ puts "Writing changed nodes..."
61
+ time = Benchmark.measure do
62
+ write_tree(tree)
63
+ end
64
+ puts "...done in " + ('%2.4f' % time.real) + ' seconds'
65
+ end while tree.node_access[:alcn].any? {|name,node| node.flagged(:created) || node.flagged(:reinit)}
66
+ :success
67
+ end
68
+
69
+ #######
70
+ private
71
+ #######
72
+
73
+ # Update the +tree+ by creating/reinitializing all needed nodes.
74
+ def update_tree(tree)
75
+ unused_paths = Set.new
76
+ begin
77
+ used_paths = Set.new(find_all_source_paths.keys) - unused_paths
78
+ paths_to_use = Set.new
79
+ nodes_to_delete = Set.new
80
+
81
+ tree.node_access[:alcn].each do |alcn, node|
82
+ next if node == tree.dummy_root
83
+ used_paths.delete(node.node_info[:src])
84
+
85
+ deleted = !find_all_source_paths.include?(node.node_info[:src])
86
+ if deleted
87
+ nodes_to_delete << node
88
+ #TODO: delete output path
89
+ elsif (!node.flagged(:created) && find_all_source_paths[node.node_info[:src]].changed?) || node.meta_info_changed?
90
+ node.flag(:reinit)
91
+ paths_to_use << node.node_info[:src]
92
+ elsif node.changed?
93
+ # nothing to be done here
94
+ end
95
+ end
96
+
97
+ nodes_to_delete.each {|node| tree.delete_node(node)}
98
+ used_paths.merge(paths_to_use)
99
+ paths = create_nodes_from_paths(tree, used_paths.to_a.sort)
100
+ unused_paths.merge(used_paths - paths)
101
+ tree.node_access[:alcn].each {|name, node| tree.delete_node(node) if node.flagged(:reinit)}
102
+ website.cache.reset_volatile_cache
103
+ end until used_paths.empty?
104
+ end
105
+
106
+ # Write out all changed nodes of the +tree+.
107
+ def write_tree(tree)
108
+ output = website.blackboard.invoke(:output_instance)
109
+
110
+ tree.node_access[:alcn].select do |name, node|
111
+ use_node = (node != tree.dummy_root && node.flagged(:dirty))
112
+ node.unflag(:dirty_meta_info)
113
+ node.unflag(:created)
114
+ node.unflag(:dirty)
115
+ use_node
116
+ end.sort.each do |name, node|
117
+ next if node['no_output'] || !(content = node.content)
118
+
119
+ begin
120
+ puts " "*4 + name, :verbose
121
+ type = if node.is_directory?
122
+ :directory
123
+ elsif node.is_fragment?
124
+ :fragment
125
+ else
126
+ :file
127
+ end
128
+ output.write(node.path, content, type)
129
+ rescue
130
+ raise RuntimeError, "Error while processing <#{node.absolute_lcn}>: #{$!.message}", $!.backtrace
131
+ end
132
+ end
133
+ end
134
+
135
+ # Return a hash with all source paths.
136
+ def find_all_source_paths
137
+ if !defined?(@paths)
138
+ source = Webgen::Source::Stacked.new(website.config['sources'].collect do |mp, name, *args|
139
+ [mp, constant(name).new(*args)]
140
+ end)
141
+ @paths = {}
142
+ source.paths.each do |path|
143
+ if !(website.config['sourcehandler.ignore'].any? {|pat| File.fnmatch(pat, path, File::FNM_CASEFOLD|File::FNM_DOTMATCH)})
144
+ @paths[path.source_path] = path
145
+ end
146
+ end
147
+ end
148
+ @paths
149
+ end
150
+
151
+ # Return only the subset of +paths+ which are handled by the source handler +name+.
152
+ def paths_for_handler(name, paths)
153
+ patterns = website.config['sourcehandler.patterns'][name]
154
+ return [] if patterns.nil?
155
+
156
+ options = (website.config['sourcehandler.casefold'] ? File::FNM_CASEFOLD : 0) |
157
+ (website.config['sourcehandler.use_hidden_files'] ? File::FNM_DOTMATCH : 0)
158
+ find_all_source_paths.values_at(*paths).select do |path|
159
+ patterns.any? {|pat| File.fnmatch(pat, path, options)}
160
+ end
161
+ end
162
+
163
+ # Use the source handlers to create nodes for the +paths+ in the +tree+.
164
+ def create_nodes_from_paths(tree, paths)
165
+ used_paths = Set.new
166
+ website.config['sourcehandler.invoke'].sort.each do |priority, shns|
167
+ shns.each do |shn|
168
+ sh = website.cache.instance(shn)
169
+ handler_paths = paths_for_handler(shn, paths)
170
+ used_paths.merge(handler_paths)
171
+ handler_paths.sort {|a,b| a.path.length <=> b.path.length}.each do |path|
172
+ parent_dir = path.directory.split('/').collect {|p| Path.new(p).cn}.join('/')
173
+ parent_dir += '/' if path != '/' && parent_dir == ''
174
+ create_nodes(tree, parent_dir, path, sh)
175
+ end
176
+ end
177
+ end
178
+ used_paths
179
+ end
180
+
181
+ # Prepare everything to create nodes under the absolute lcn path +parent_path_name+ in the
182
+ # +tree from the +path+ using the +source_handler+. If a block is given, the actual creation
183
+ # of the nodes is deferred to it. After the nodes are created, it is also checked if they have
184
+ # all needed properties.
185
+ def create_nodes(tree, parent_path_name, path, source_handler) #:yields: parent, path
186
+ if !(parent = tree[parent_path_name])
187
+ raise "The specified parent path <#{parent_path_name}> does not exist"
188
+ end
189
+ path = path.dup
190
+ path.meta_info = default_meta_info(path, source_handler.class.name)
191
+ (website.cache[:sourcehandler_path_mi] ||= {})[[path.path, source_handler.class.name]] = path.meta_info.dup
192
+ website.blackboard.dispatch_msg(:before_node_created, parent, path)
193
+ *nodes = if block_given?
194
+ yield(parent, path)
195
+ else
196
+ source_handler.create_node(parent, path)
197
+ end
198
+ nodes.flatten.compact.each do |node|
199
+ website.blackboard.dispatch_msg(:after_node_created, node)
200
+ end
201
+ nodes
202
+ end
203
+
204
+ # Return the default meta info for the pair of +path+ and +sh_name+.
205
+ def default_meta_info(path, sh_name)
206
+ path.meta_info.merge(website.config['sourcehandler.default_meta_info'][:all]).
207
+ merge(website.config['sourcehandler.default_meta_info'][sh_name] || {})
208
+ end
209
+
210
+ # Check if the default meta information for +node+ has changed since the last run. But don't
211
+ # take the node's path's +modified_at+ meta information into account since that changes on
212
+ # every path change.
213
+ def meta_info_changed?(node)
214
+ path = node.node_info[:creation_path]
215
+ old_mi = website.cache[:sourcehandler_path_mi][[path, node.node_info[:processor]]]
216
+ old_mi.delete('modified_at')
217
+ new_mi = default_meta_info(@paths[path] || Webgen::Path.new(path), node.node_info[:processor])
218
+ new_mi.delete('modified_at')
219
+ node.flag(:dirty_meta_info) if !old_mi || old_mi != new_mi
220
+ end
221
+
222
+ end
223
+
224
+ end
225
+
226
+ end