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,37 @@
1
+ module Webgen
2
+
3
+ # Namespace for all classes that know how to write out node content.
4
+ #
5
+ # = Implementing an output class
6
+ #
7
+ # Output classes know how to write rendered node data to an output location.
8
+ #
9
+ # An output class must respond to three methods
10
+ #
11
+ # <tt>exists?(path)</tt>::
12
+ # Return +true+ if the output path exists.
13
+ # <tt>delete(path)</tt>::
14
+ # Delete the given output path.
15
+ # <tt>write(path, data, type)</tt>::
16
+ # Write the data to the given output path. The parameter +type+ specifies the type of the
17
+ # to be written path: +:file+ or +:directory+.
18
+ # <tt>read(path)</tt>:
19
+ # Return the content of the given path if it exists or raise an error otherwise.
20
+ #
21
+ module Output
22
+
23
+ autoload :FileSystem, 'webgen/output/filesystem'
24
+
25
+ # Returns an instance of the configured output class.
26
+ def self.instance
27
+ classes = (WebsiteAccess.website.cache.volatile[:classes] ||= {})
28
+ unless classes.has_key?(:output_instance)
29
+ klass, *args = WebsiteAccess.website.config['output']
30
+ classes[:output_instance] = Object.constant(klass).new(*args)
31
+ end
32
+ classes[:output_instance]
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,67 @@
1
+ require 'fileutils'
2
+
3
+ module Webgen::Output
4
+
5
+ # This class uses the file systems as output device. On initialization a +root+ path is set and
6
+ # all other operations are taken relative to this root path.
7
+ class FileSystem
8
+
9
+ include Webgen::WebsiteAccess
10
+
11
+ # The root path, ie. the path to which the root node gets rendered.
12
+ attr_reader :root
13
+
14
+ # Create a new object with the given +root+ path. If +root+ is not absolute, it is taken
15
+ # relative to the website directory.
16
+ def initialize(root)
17
+ #TODO: copied from source/filesystem.rb
18
+ if root =~ /^([a-zA-Z]:|\/)/
19
+ @root = root
20
+ else
21
+ @root = File.join(website.directory, root)
22
+ end
23
+ end
24
+
25
+ # Return +true+ if the given path exists.
26
+ def exists?(path)
27
+ File.exists?(File.join(@root, path))
28
+ end
29
+
30
+ # Delete the given +path+
31
+ def delete(path)
32
+ dest = File.join(@root, path)
33
+ if File.directory?(dest)
34
+ FileUtils.rm_rf(dest)
35
+ else
36
+ FileUtils.rm(dest)
37
+ end
38
+ end
39
+
40
+ # Write the +data+ to the given +path+. The +type+ parameter specifies the type of the path to
41
+ # be created which can either be <tt>:file</tt> or <tt>:directory</tt>.
42
+ def write(path, data, type = :file)
43
+ dest = File.join(@root, path)
44
+ FileUtils.makedirs(File.dirname(dest))
45
+ if type == :directory
46
+ FileUtils.makedirs(dest)
47
+ elsif type == :file
48
+ if data.kind_of?(String)
49
+ File.open(dest, 'wb') {|f| f.write(data) }
50
+ else
51
+ data.stream do |source|
52
+ File.open(dest, 'wb') {|f| FileUtils.copy_stream(source, f) }
53
+ end
54
+ end
55
+ else
56
+ raise "Unsupported path type '#{type}' for #{path}"
57
+ end
58
+ end
59
+
60
+ # Return the content of the given +path+.
61
+ def read(path)
62
+ File.open(File.join(@root, path), 'rb') {|f| f.read}
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,133 @@
1
+ require 'yaml'
2
+
3
+ module Webgen
4
+
5
+ # A single block within a Page object. The content of the block can be rendered using the #render method.
6
+ class Block
7
+
8
+ # The name of the block.
9
+ attr_reader :name
10
+
11
+ # The content of the block.
12
+ attr_reader :content
13
+
14
+ # The options set specifically for this block.
15
+ attr_reader :options
16
+
17
+ # Create a new block with the name +name+ and the given +content+ and +options+.
18
+ def initialize(name, content, options)
19
+ @name, @content, @options = name, content, options
20
+ end
21
+
22
+ # Render the block using the provided context object. Uses the content processors specified in
23
+ # the +pipeline+ key of the +options+ attribute to do the actual rendering.
24
+ #
25
+ # Returns the given context with the rendered content.
26
+ def render(context)
27
+ context[:content] = @content.dup
28
+ context[:block] = self
29
+ @options['pipeline'].to_s.split(/,/).each do |processor|
30
+ raise "No such content processor available: #{processor}" unless context[:processors].has_key?(processor)
31
+ context[:processors][processor].call(context)
32
+ end
33
+ context
34
+ end
35
+
36
+ end
37
+
38
+
39
+ # Raised during parsing of data in Webgen Page Format if the data is invalid.
40
+ class WebgenPageFormatError < RuntimeError; end
41
+
42
+ # A Page object wraps a meta information hash and an array of Block objects. It is normally
43
+ # generated from a file or string in Webgen Page Format using the provided class methods.
44
+ class Page
45
+
46
+ RE_META_INFO_START = /\A---\s*(?:\n|\r|\r\n)/m
47
+ RE_META_INFO = /\A---\s*(?:\n|\r|\r\n).*?(?:\n|\r|\r\n)(?=---.*?(?:\n|\r|\r\n)|\Z)/m
48
+ RE_BLOCKS_OPTIONS = /^--- *?(?: *((?:\w+:[^\s]* *)*))?$|^$/
49
+ RE_BLOCKS_START = /^--- .*?$|^--- *$/
50
+ RE_BLOCKS = /(?:(#{RE_BLOCKS_START})|\A)(.*?)(?:(?=#{RE_BLOCKS_START})|\Z)/m
51
+
52
+ class << self
53
+
54
+ # Parse the given string +data+ in Webgen Page Format and initialize a new Page object with
55
+ # the information. The +meta_info+ parameter can be used to provide default meta information.
56
+ def from_data(data, meta_info = {})
57
+ md = /(#{RE_META_INFO})?(.*)/m.match(normalize_eol(data))
58
+ if md[1].nil? && data =~ RE_META_INFO_START
59
+ raise WebgenPageFormatError, 'Found start line for meta information block but no valid meta information block'
60
+ end
61
+ meta_info = meta_info.merge(md[1].nil? ? {} : parse_meta_info(md[1]))
62
+ blocks = parse_blocks(md[2] || '', meta_info)
63
+ new(meta_info, blocks)
64
+ end
65
+
66
+ #######
67
+ private
68
+ #######
69
+
70
+ # Normalize the end-of-line encodings to Unix style.
71
+ def normalize_eol(data)
72
+ data.gsub(/\r\n?/, "\n")
73
+ end
74
+
75
+ # Parse the meta info string +data+ and return the hash with the meta information.
76
+ def parse_meta_info(data)
77
+ begin
78
+ meta_info = YAML::load(data)
79
+ unless meta_info.kind_of?(Hash)
80
+ raise WebgenPageFormatError, "Invalid structure of meta information block: expected YAML hash but found #{meta_info.class}"
81
+ end
82
+ rescue ArgumentError => e
83
+ raise WebgenPageFormatError, e.message
84
+ end
85
+ meta_info
86
+ end
87
+
88
+ # Parse all blocks in +data+ and return them. Meta information can be provided in +meta_info+
89
+ # which is used for setting the block names and options.
90
+ def parse_blocks(data, meta_info)
91
+ scanned = data.scan(RE_BLOCKS)
92
+ raise(WebgenPageFormatError, 'No content blocks specified') if scanned.length == 0
93
+
94
+ blocks = {}
95
+ scanned.each_with_index do |block_data, index|
96
+ options, content = *block_data
97
+ md = RE_BLOCKS_OPTIONS.match(options.to_s)
98
+ raise(WebgenPageFormatError, "Found invalid blocks starting line for block #{index+1}: #{options}") if content =~ /\A---/ || md.nil?
99
+ options = Hash[*md[1].to_s.scan(/(\w+):([^\s]*)/).map {|k,v| [k, YAML::load(v)]}.flatten]
100
+ options = (meta_info['blocks']['default'] || {} rescue {}).
101
+ merge((meta_info['blocks'][index+1] || {} rescue {})).
102
+ merge(options)
103
+
104
+ name = options.delete('name') || (index == 0 ? 'content' : 'block' + (index + 1).to_s)
105
+ raise(WebgenPageFormatError, "Previously used name '#{name}' also used for block #{index+1}") if blocks.has_key?(name)
106
+ content ||= ''
107
+ content.gsub!(/^(\\+)(---.*?)$/) {|m| "\\" * ($1.length / 2) + $2}
108
+ content.strip!
109
+ blocks[name] = blocks[index+1] = Block.new(name, content, options)
110
+ end
111
+ meta_info.delete('blocks')
112
+ blocks
113
+ end
114
+
115
+ end
116
+
117
+
118
+ # The contents of the meta information block.
119
+ attr_reader :meta_info
120
+
121
+ # The array of blocks for the page.
122
+ attr_reader :blocks
123
+
124
+ # Create a new Page object with the meta information provided in +meta_info+ and the given
125
+ # +blocks+.
126
+ def initialize(meta_info = {}, blocks = nil)
127
+ @meta_info = meta_info
128
+ @blocks = blocks
129
+ end
130
+
131
+ end
132
+
133
+ end
@@ -0,0 +1,182 @@
1
+ require 'webgen/languages'
2
+
3
+ module Webgen
4
+
5
+ # A path object provides information about a specific path as well as methods for accessing its
6
+ # content.
7
+ #
8
+ # A webgen source class needs to derive a specialized path class from this class and implement an
9
+ # approriate #changed? method that returns +true+ if the path's content has changed since the last
10
+ # webgen run.
11
+ class Path
12
+
13
+ # Helper class for easy access to the content of a path.
14
+ class SourceIO
15
+
16
+ # Create a new SourceIO object. A block has to be specified that returns an IO object.
17
+ def initialize(&block)
18
+ @block = block
19
+ raise ArgumentError, 'Need to provide a block which returns an IO object' if @block.nil?
20
+ end
21
+
22
+ # Provide direct access to the wrapped IO object.
23
+ def stream
24
+ io = @block.call
25
+ yield(io)
26
+ ensure
27
+ io.close
28
+ end
29
+
30
+ # Return the content of the wrapped IO object as string.
31
+ def data
32
+ stream {|io| io.read}
33
+ end
34
+
35
+ end
36
+
37
+
38
+ include Comparable
39
+
40
+ # The full source path.
41
+ attr_accessor :path
42
+
43
+ # The basename part of the path.
44
+ attr_accessor :basename
45
+
46
+ # The directory part of the path.
47
+ attr_accessor :directory
48
+
49
+ # The canonical name without the extension.
50
+ attr_accessor :cnbase
51
+
52
+ # The extension.
53
+ attr_accessor :ext
54
+
55
+ # Extracted meta information for the path.
56
+ attr_accessor :meta_info
57
+
58
+ # Create a new Path object for +path+. The optional block needs to return an IO object for the
59
+ # content of the path.
60
+ def initialize(path, &ioblock)
61
+ @meta_info = {}
62
+ @io = SourceIO.new(&ioblock) if block_given?
63
+ analyse(path)
64
+ end
65
+
66
+ # Mount this path at the mount point +mp+ optionally stripping +prefix+ from the path and return
67
+ # the new path object.
68
+ def mount_at(mp, prefix = nil)
69
+ temp = dup
70
+ temp.path = temp.path.sub(/^#{Regexp.escape(prefix.chomp("/"))}/, '') if prefix #"
71
+ reanalyse = (@path == '/' || temp.path == '/')
72
+ temp.path = File.join(mp, temp.path)
73
+ if reanalyse
74
+ temp.send(:analyse, temp.path)
75
+ else
76
+ temp.directory = File.join(File.dirname(temp.path), '/')
77
+ end
78
+ temp
79
+ end
80
+
81
+ # Has the content of this path changed since the last webgen run? This default implementation
82
+ # always returns +true+, a specialized sub class needs to override this behaviour!
83
+ def changed?
84
+ true
85
+ end
86
+
87
+ # Duplicate the path object.
88
+ def dup
89
+ temp = super
90
+ temp.meta_info = @meta_info.dup
91
+ temp
92
+ end
93
+
94
+ # The IO object associated with the path.
95
+ def io
96
+ if @io
97
+ @io
98
+ else
99
+ raise "No IO object defined for the path #{self}"
100
+ end
101
+ end
102
+
103
+ # The canonical name created from the filename (created from cnbase and extension).
104
+ def cn
105
+ @cnbase + (@ext.length > 0 ? '.' + @ext : '')
106
+ end
107
+
108
+ # Utility method for creating the lcn from +cn+ and the language +lang+.
109
+ def self.lcn(cn, lang)
110
+ if lang.nil?
111
+ cn
112
+ else
113
+ cn.split('.').insert(1, lang.to_s).join('.')
114
+ end
115
+ end
116
+
117
+ # The localized canonical name created from the filename.
118
+ def lcn
119
+ self.class.lcn(cn, @meta_info['lang'])
120
+ end
121
+
122
+ # Compare this object to another Path or a String.
123
+ def ==(other)
124
+ if other.kind_of?(Path)
125
+ other.path == @path
126
+ elsif other.kind_of?(String)
127
+ other == @path
128
+ else
129
+ false
130
+ end
131
+ end
132
+ alias_method(:eql?, :==)
133
+
134
+ # Return +true+ if the localized path matches the given +pattern+. For information on which
135
+ # patterns are supported, have a look at the documentation of File.fnmatch.
136
+ def =~(pattern)
137
+ File.fnmatch(pattern, File.join(@directory, lcn), File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
138
+ end
139
+
140
+ # Implemented sothat a Path looks like a String when used as key in a hash.
141
+ def <=>(other)
142
+ @path <=> other.to_str
143
+ end
144
+
145
+ # Implemented sothat a Path looks like a String when used as key in a hash.
146
+ def hash
147
+ @path.hash
148
+ end
149
+
150
+ def to_s #:nodoc:
151
+ @path.dup
152
+ end
153
+ alias_method :to_str, :to_s
154
+
155
+ def inspect #:nodoc:
156
+ "#<Path: #{@path}>"
157
+ end
158
+
159
+ #######
160
+ private
161
+ #######
162
+
163
+ FILENAME_RE = /^(?:(\d+)\.)?([^.]*?)(?:\.(\w\w\w?)(?=.))?(?:\.(.*))?$/
164
+
165
+ # Analyse the +path+ and fill the object with the extracted information.
166
+ def analyse(path)
167
+ @path = path
168
+ @basename = File.basename(path)
169
+ @directory = File.join(File.dirname(path), '/')
170
+ matchData = FILENAME_RE.match(@basename)
171
+
172
+ @meta_info['sort_info'] = (matchData[1].nil? ? nil : matchData[1].to_i)
173
+ @cnbase = matchData[2]
174
+ @meta_info['lang'] = Webgen::LanguageManager.language_for_code(matchData[3])
175
+ @ext = (@meta_info['lang'].nil? && !matchData[3].nil? ? matchData[3].to_s + '.' : '') + matchData[4].to_s
176
+
177
+ @meta_info['title'] = @cnbase.tr('_-', ' ').capitalize
178
+ end
179
+
180
+ end
181
+
182
+ end
@@ -0,0 +1,24 @@
1
+ module Webgen
2
+
3
+ # Namespace for all classes that provide source paths.
4
+ #
5
+ # = Implementing a source class
6
+ #
7
+ # Source classes provide access to the source paths on which the source handlers act.
8
+ #
9
+ # A source class only needs to respond to the method +paths+ which needs to return a set of paths
10
+ # for the source. The returned paths must respond to the method <tt>changed?</tt> (has to return
11
+ # +true+ if the paths has changed since the last webgen run) which is not implemented in the
12
+ # default Path class. One can either derive a specialized path class or define singleton methods
13
+ # on each path object.
14
+ #
15
+ module Source
16
+
17
+ autoload :Base, 'webgen/source/base'
18
+ autoload :FileSystem, 'webgen/source/filesystem'
19
+ autoload :Stacked, 'webgen/source/stacked'
20
+ autoload :Resource, 'webgen/source/resource'
21
+
22
+ end
23
+
24
+ end