webgen 0.5.17 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (408) hide show
  1. data/API.rdoc +143 -0
  2. data/AUTHORS +0 -1
  3. data/COPYING +17 -8
  4. data/ChangeLog +4456 -0
  5. data/GPL +623 -289
  6. data/README.md +71 -0
  7. data/Rakefile +87 -99
  8. data/VERSION +1 -1
  9. data/bin/webgen +1 -7
  10. data/data/webgen/basic_website_template/ext/init.rb +15 -0
  11. data/data/webgen/basic_website_template/webgen.config +18 -0
  12. data/data/webgen/bundle_template_files/README.md.erb +24 -0
  13. data/data/webgen/bundle_template_files/Rakefile.erb +36 -0
  14. data/data/webgen/bundle_template_files/info.yaml.erb +16 -0
  15. data/data/webgen/bundle_template_files/init.rb.erb +1 -0
  16. data/data/webgen/passive_sources/default.metainfo +32 -0
  17. data/data/webgen/passive_sources/stylesheets/coderay-default.css +109 -118
  18. data/data/webgen/passive_sources/templates/feed.template +62 -0
  19. data/data/webgen/passive_sources/templates/sitemap.template +3 -6
  20. data/data/webgen/passive_sources/templates/tag.template +42 -0
  21. data/data/webgen/website_bundles/default/README +2 -2
  22. data/lib/webgen/blackboard.rb +15 -51
  23. data/lib/webgen/bundle/built-in-show-changes/init.rb +54 -0
  24. data/lib/webgen/bundle/built-in/init.rb +366 -0
  25. data/lib/webgen/bundle_loader.rb +126 -0
  26. data/lib/webgen/cache.rb +9 -18
  27. data/lib/webgen/cli.rb +131 -58
  28. data/lib/webgen/cli/bundle_command.rb +30 -0
  29. data/lib/webgen/cli/create_bundle_command.rb +46 -0
  30. data/lib/webgen/cli/create_command.rb +48 -60
  31. data/lib/webgen/cli/generate_command.rb +25 -0
  32. data/lib/webgen/cli/install_bundle_command.rb +34 -0
  33. data/lib/webgen/cli/list_bundle_command.rb +108 -0
  34. data/lib/webgen/cli/logger.rb +45 -0
  35. data/lib/webgen/cli/show_command.rb +30 -0
  36. data/lib/webgen/cli/show_config_command.rb +63 -0
  37. data/lib/webgen/cli/show_dependencies_command.rb +103 -0
  38. data/lib/webgen/cli/show_extensions_command.rb +74 -0
  39. data/lib/webgen/cli/utils.rb +68 -95
  40. data/lib/webgen/configuration.rb +143 -105
  41. data/lib/webgen/content_processor.rb +160 -0
  42. data/lib/webgen/content_processor/blocks.rb +96 -0
  43. data/lib/webgen/content_processor/builder.rb +25 -0
  44. data/lib/webgen/content_processor/erb.rb +25 -0
  45. data/lib/webgen/content_processor/erubis.rb +31 -0
  46. data/lib/webgen/content_processor/fragments.rb +82 -0
  47. data/lib/webgen/content_processor/haml.rb +25 -0
  48. data/lib/webgen/content_processor/html_head.rb +157 -0
  49. data/lib/webgen/content_processor/kramdown.rb +49 -0
  50. data/lib/webgen/content_processor/maruku.rb +39 -0
  51. data/lib/webgen/content_processor/r_discount.rb +21 -0
  52. data/lib/webgen/content_processor/rdoc.rb +22 -0
  53. data/lib/webgen/content_processor/redcloth.rb +23 -0
  54. data/lib/webgen/content_processor/ruby.rb +20 -0
  55. data/lib/webgen/content_processor/sass.rb +145 -0
  56. data/lib/webgen/content_processor/scss.rb +23 -0
  57. data/lib/webgen/content_processor/tags.rb +30 -0
  58. data/lib/webgen/content_processor/tidy.rb +32 -0
  59. data/lib/webgen/content_processor/tikz.rb +116 -0
  60. data/lib/webgen/content_processor/xmllint.rb +31 -0
  61. data/lib/webgen/context.rb +57 -29
  62. data/lib/webgen/context/html_head.rb +60 -0
  63. data/lib/webgen/context/nodes.rb +32 -27
  64. data/lib/webgen/context/rendering.rb +39 -0
  65. data/lib/webgen/context/webgen_tags.rb +25 -0
  66. data/lib/webgen/core_ext.rb +25 -0
  67. data/lib/webgen/destination.rb +151 -0
  68. data/lib/webgen/destination/file_system.rb +62 -0
  69. data/lib/webgen/error.rb +59 -49
  70. data/lib/webgen/extension_manager.rb +121 -0
  71. data/lib/webgen/item_tracker.rb +237 -0
  72. data/lib/webgen/item_tracker/file.rb +39 -0
  73. data/lib/webgen/item_tracker/missing_node.rb +61 -0
  74. data/lib/webgen/item_tracker/node_content.rb +40 -0
  75. data/lib/webgen/item_tracker/node_meta_info.rb +53 -0
  76. data/lib/webgen/item_tracker/nodes.rb +92 -0
  77. data/lib/webgen/logger.rb +26 -82
  78. data/lib/webgen/node.rb +122 -367
  79. data/lib/webgen/node_finder.rb +336 -0
  80. data/lib/webgen/page.rb +48 -85
  81. data/lib/webgen/path.rb +218 -156
  82. data/lib/webgen/path_handler.rb +400 -0
  83. data/lib/webgen/path_handler/base.rb +220 -0
  84. data/lib/webgen/path_handler/copy.rb +78 -0
  85. data/lib/webgen/path_handler/directory.rb +21 -0
  86. data/lib/webgen/path_handler/feed.rb +82 -0
  87. data/lib/webgen/path_handler/meta_info.rb +84 -0
  88. data/lib/webgen/path_handler/page.rb +38 -0
  89. data/lib/webgen/path_handler/page_utils.rb +79 -0
  90. data/lib/webgen/path_handler/sitemap.rb +52 -0
  91. data/lib/webgen/path_handler/template.rb +96 -0
  92. data/lib/webgen/path_handler/virtual.rb +85 -0
  93. data/lib/webgen/{webgentask.rb → rake_task.rb} +31 -27
  94. data/lib/webgen/source.rb +106 -24
  95. data/lib/webgen/source/file_system.rb +41 -0
  96. data/lib/webgen/source/stacked.rb +49 -53
  97. data/lib/webgen/source/tar_archive.rb +59 -0
  98. data/lib/webgen/tag.rb +250 -19
  99. data/lib/webgen/tag/breadcrumb_trail.rb +65 -0
  100. data/lib/webgen/tag/coderay.rb +32 -35
  101. data/lib/webgen/tag/date.rb +9 -9
  102. data/lib/webgen/tag/execute_command.rb +31 -0
  103. data/lib/webgen/tag/include_file.rb +32 -0
  104. data/lib/webgen/tag/langbar.rb +31 -47
  105. data/lib/webgen/tag/link.rb +17 -18
  106. data/lib/webgen/tag/menu.rb +27 -189
  107. data/lib/webgen/tag/meta_info.rb +31 -0
  108. data/lib/webgen/tag/relocatable.rb +48 -39
  109. data/lib/webgen/tag/tikz.rb +24 -100
  110. data/lib/webgen/task.rb +99 -0
  111. data/lib/webgen/task/create_bundle.rb +73 -0
  112. data/lib/webgen/task/create_website.rb +94 -0
  113. data/lib/webgen/task/generate_website.rb +47 -0
  114. data/lib/webgen/test_helper.rb +183 -0
  115. data/lib/webgen/tree.rb +95 -46
  116. data/lib/webgen/utils.rb +39 -0
  117. data/lib/webgen/utils/external_command.rb +27 -0
  118. data/lib/webgen/utils/tag_parser.rb +124 -0
  119. data/lib/webgen/version.rb +1 -1
  120. data/lib/webgen/website.rb +134 -296
  121. data/setup.rb +1 -1
  122. data/test/test_documentation.rb +43 -0
  123. data/test/webgen/cli/test_logger.rb +41 -0
  124. data/test/{test_contentprocessor_blocks.rb → webgen/content_processor/test_blocks.rb} +30 -28
  125. data/test/webgen/content_processor/test_builder.rb +25 -0
  126. data/test/webgen/content_processor/test_erb.rb +21 -0
  127. data/test/webgen/content_processor/test_erubis.rb +33 -0
  128. data/test/webgen/content_processor/test_fragments.rb +96 -0
  129. data/test/webgen/content_processor/test_haml.rb +24 -0
  130. data/test/webgen/content_processor/test_html_head.rb +78 -0
  131. data/test/webgen/content_processor/test_kramdown.rb +49 -0
  132. data/test/webgen/content_processor/test_maruku.rb +30 -0
  133. data/test/webgen/content_processor/test_r_discount.rb +18 -0
  134. data/test/webgen/content_processor/test_rdoc.rb +18 -0
  135. data/test/webgen/content_processor/test_redcloth.rb +23 -0
  136. data/test/webgen/content_processor/test_ruby.rb +24 -0
  137. data/test/webgen/content_processor/test_sass.rb +44 -0
  138. data/test/webgen/content_processor/test_scss.rb +23 -0
  139. data/test/webgen/content_processor/test_tags.rb +44 -0
  140. data/test/webgen/content_processor/test_tidy.rb +31 -0
  141. data/test/webgen/content_processor/test_tikz.rb +33 -0
  142. data/test/webgen/content_processor/test_xmllint.rb +32 -0
  143. data/test/webgen/destination/test_file_system.rb +54 -0
  144. data/test/webgen/item_tracker/test_file.rb +31 -0
  145. data/test/webgen/item_tracker/test_missing_node.rb +70 -0
  146. data/test/webgen/item_tracker/test_node_content.rb +42 -0
  147. data/test/webgen/item_tracker/test_node_meta_info.rb +44 -0
  148. data/test/webgen/item_tracker/test_nodes.rb +61 -0
  149. data/test/webgen/path_handler/test_base.rb +153 -0
  150. data/test/webgen/path_handler/test_copy.rb +56 -0
  151. data/test/webgen/path_handler/test_feed.rb +85 -0
  152. data/test/webgen/path_handler/test_meta_info.rb +98 -0
  153. data/test/webgen/path_handler/test_page.rb +25 -0
  154. data/test/webgen/path_handler/test_page_utils.rb +59 -0
  155. data/test/webgen/path_handler/test_sitemap.rb +95 -0
  156. data/test/webgen/path_handler/test_template.rb +64 -0
  157. data/test/webgen/path_handler/test_virtual.rb +87 -0
  158. data/test/webgen/source/test_file_system.rb +51 -0
  159. data/test/webgen/source/test_stacked.rb +35 -0
  160. data/test/{test_source_tararchive.rb → webgen/source/test_tar_archive.rb} +10 -25
  161. data/test/webgen/tag/test_breadcrumb_trail.rb +66 -0
  162. data/test/webgen/tag/test_coderay.rb +34 -0
  163. data/test/webgen/tag/test_date.rb +18 -0
  164. data/test/webgen/tag/test_execute_command.rb +36 -0
  165. data/test/webgen/tag/test_include_file.rb +35 -0
  166. data/test/webgen/tag/test_langbar.rb +50 -0
  167. data/test/webgen/tag/test_link.rb +40 -0
  168. data/test/webgen/tag/test_menu.rb +61 -0
  169. data/test/webgen/tag/test_meta_info.rb +25 -0
  170. data/test/webgen/tag/test_relocatable.rb +50 -0
  171. data/test/webgen/tag/test_tikz.rb +41 -0
  172. data/test/webgen/task/test_create_website.rb +46 -0
  173. data/test/webgen/test_blackboard.rb +31 -0
  174. data/test/webgen/test_bundle_loader.rb +55 -0
  175. data/test/{test_cache.rb → webgen/test_cache.rb} +3 -15
  176. data/test/webgen/test_cli.rb +41 -0
  177. data/test/webgen/test_configuration.rb +131 -0
  178. data/test/webgen/test_content_processor.rb +86 -0
  179. data/test/webgen/test_context.rb +73 -0
  180. data/test/webgen/test_core_ext.rb +20 -0
  181. data/test/webgen/test_destination.rb +48 -0
  182. data/test/webgen/test_error.rb +121 -0
  183. data/test/webgen/test_extension_manager.rb +70 -0
  184. data/test/webgen/test_item_tracker.rb +106 -0
  185. data/test/{test_languages.rb → webgen/test_languages.rb} +4 -4
  186. data/test/webgen/test_logger.rb +46 -0
  187. data/test/webgen/test_node.rb +178 -0
  188. data/test/webgen/test_node_finder.rb +127 -0
  189. data/test/{test_page.rb → webgen/test_page.rb} +44 -48
  190. data/test/webgen/test_path.rb +271 -0
  191. data/test/{test_webgentask.rb → webgen/test_rake_task.rb} +4 -4
  192. data/test/webgen/test_source.rb +59 -0
  193. data/test/webgen/test_tag.rb +137 -0
  194. data/test/webgen/test_task.rb +40 -0
  195. data/test/webgen/test_tree.rb +147 -0
  196. data/test/webgen/test_utils.rb +16 -0
  197. data/test/webgen/test_website.rb +45 -0
  198. data/test/webgen/utils/test_tag_parser.rb +99 -0
  199. metadata +292 -344
  200. data/data/webgen/passive_sources/templates/atom_feed.template +0 -39
  201. data/data/webgen/passive_sources/templates/rss_feed.template +0 -28
  202. data/data/webgen/resources.yaml +0 -4
  203. data/data/webgen/webgui/app.rb +0 -11
  204. data/data/webgen/webgui/controller/main.rb +0 -135
  205. data/data/webgen/webgui/layout/default.xhtml +0 -40
  206. data/data/webgen/webgui/overrides/win32console.rb +0 -0
  207. data/data/webgen/webgui/public/css/jquery.autocomplete.css +0 -50
  208. data/data/webgen/webgui/public/css/ramaze_error.css +0 -90
  209. data/data/webgen/webgui/public/css/style.css +0 -55
  210. data/data/webgen/webgui/public/img/headerbg.jpg +0 -0
  211. data/data/webgen/webgui/public/img/webgen_logo.png +0 -0
  212. data/data/webgen/webgui/public/js/jquery.autocomplete.js +0 -15
  213. data/data/webgen/webgui/public/js/jquery.js +0 -32
  214. data/data/webgen/webgui/start.rb +0 -9
  215. data/data/webgen/webgui/view/create_website.xhtml +0 -14
  216. data/data/webgen/webgui/view/error.xhtml +0 -64
  217. data/data/webgen/webgui/view/index.xhtml +0 -22
  218. data/data/webgen/webgui/view/manage_website.xhtml +0 -18
  219. data/data/webgen/website_skeleton/README +0 -10
  220. data/data/webgen/website_skeleton/Rakefile +0 -69
  221. data/data/webgen/website_skeleton/config.yaml +0 -35
  222. data/data/webgen/website_skeleton/ext/init.rb +0 -10
  223. data/doc/contentprocessor.template +0 -11
  224. data/doc/contentprocessor/blocks.page +0 -129
  225. data/doc/contentprocessor/builder.page +0 -79
  226. data/doc/contentprocessor/erb.page +0 -60
  227. data/doc/contentprocessor/erubis.page +0 -46
  228. data/doc/contentprocessor/fragments.page +0 -26
  229. data/doc/contentprocessor/haml.page +0 -46
  230. data/doc/contentprocessor/head.page +0 -31
  231. data/doc/contentprocessor/kramdown.page +0 -49
  232. data/doc/contentprocessor/less.page +0 -34
  233. data/doc/contentprocessor/maruku.page +0 -44
  234. data/doc/contentprocessor/rdiscount.page +0 -37
  235. data/doc/contentprocessor/rdoc.page +0 -36
  236. data/doc/contentprocessor/redcloth.page +0 -41
  237. data/doc/contentprocessor/sass.page +0 -31
  238. data/doc/contentprocessor/scss.page +0 -39
  239. data/doc/contentprocessor/tags.page +0 -73
  240. data/doc/contentprocessor/tidy.page +0 -14
  241. data/doc/contentprocessor/xmllint.page +0 -14
  242. data/doc/extensions.metainfo +0 -29
  243. data/doc/extensions.page +0 -15
  244. data/doc/extensions.template +0 -17
  245. data/doc/faq.page +0 -222
  246. data/doc/getting_started.page +0 -135
  247. data/doc/index.page +0 -71
  248. data/doc/manual.page +0 -727
  249. data/doc/reference_configuration.page +0 -1254
  250. data/doc/reference_metainfo.page +0 -265
  251. data/doc/reference_website_styles.page +0 -32
  252. data/doc/source/filesystem.page +0 -41
  253. data/doc/source/tararchive.page +0 -40
  254. data/doc/sourcehandler.template +0 -23
  255. data/doc/sourcehandler/copy.page +0 -19
  256. data/doc/sourcehandler/directory.page +0 -27
  257. data/doc/sourcehandler/feed.page +0 -102
  258. data/doc/sourcehandler/metainfo.page +0 -48
  259. data/doc/sourcehandler/page.page +0 -14
  260. data/doc/sourcehandler/sitemap.page +0 -46
  261. data/doc/sourcehandler/template.page +0 -45
  262. data/doc/sourcehandler/virtual.page +0 -49
  263. data/doc/tag.template +0 -25
  264. data/doc/tag/breadcrumbtrail.page +0 -40
  265. data/doc/tag/coderay.page +0 -53
  266. data/doc/tag/date.page +0 -31
  267. data/doc/tag/executecommand.page +0 -26
  268. data/doc/tag/includefile.page +0 -32
  269. data/doc/tag/langbar.page +0 -47
  270. data/doc/tag/link.page +0 -44
  271. data/doc/tag/menu.page +0 -109
  272. data/doc/tag/metainfo.page +0 -29
  273. data/doc/tag/relocatable.page +0 -38
  274. data/doc/tag/sitemap.page +0 -31
  275. data/doc/tag/tikz.page +0 -159
  276. data/doc/upgrading.page +0 -138
  277. data/doc/webgen_page_format.page +0 -129
  278. data/doc/website_styles.metainfo +0 -8
  279. data/lib/webgen/cli/apply_command.rb +0 -66
  280. data/lib/webgen/cli/run_command.rb +0 -22
  281. data/lib/webgen/cli/webgui_command.rb +0 -68
  282. data/lib/webgen/common.rb +0 -27
  283. data/lib/webgen/common/sitemap.rb +0 -83
  284. data/lib/webgen/contentprocessor.rb +0 -117
  285. data/lib/webgen/contentprocessor/blocks.rb +0 -92
  286. data/lib/webgen/contentprocessor/builder.rb +0 -29
  287. data/lib/webgen/contentprocessor/erb.rb +0 -26
  288. data/lib/webgen/contentprocessor/erubis.rb +0 -39
  289. data/lib/webgen/contentprocessor/fragments.rb +0 -25
  290. data/lib/webgen/contentprocessor/haml.rb +0 -34
  291. data/lib/webgen/contentprocessor/head.rb +0 -128
  292. data/lib/webgen/contentprocessor/kramdown.rb +0 -27
  293. data/lib/webgen/contentprocessor/kramdown/html.rb +0 -36
  294. data/lib/webgen/contentprocessor/less.rb +0 -35
  295. data/lib/webgen/contentprocessor/maruku.rb +0 -36
  296. data/lib/webgen/contentprocessor/rdiscount.rb +0 -19
  297. data/lib/webgen/contentprocessor/rdoc.rb +0 -20
  298. data/lib/webgen/contentprocessor/redcloth.rb +0 -21
  299. data/lib/webgen/contentprocessor/sass.rb +0 -22
  300. data/lib/webgen/contentprocessor/scss.rb +0 -22
  301. data/lib/webgen/contentprocessor/tags.rb +0 -170
  302. data/lib/webgen/contentprocessor/tidy.rb +0 -38
  303. data/lib/webgen/contentprocessor/xmllint.rb +0 -37
  304. data/lib/webgen/context/render.rb +0 -32
  305. data/lib/webgen/context/tags.rb +0 -20
  306. data/lib/webgen/coreext.rb +0 -13
  307. data/lib/webgen/default_config.rb +0 -240
  308. data/lib/webgen/loggable.rb +0 -25
  309. data/lib/webgen/output.rb +0 -86
  310. data/lib/webgen/output/filesystem.rb +0 -69
  311. data/lib/webgen/source/filesystem.rb +0 -61
  312. data/lib/webgen/source/resource.rb +0 -45
  313. data/lib/webgen/source/tararchive.rb +0 -78
  314. data/lib/webgen/sourcehandler.rb +0 -275
  315. data/lib/webgen/sourcehandler/base.rb +0 -281
  316. data/lib/webgen/sourcehandler/copy.rb +0 -44
  317. data/lib/webgen/sourcehandler/directory.rb +0 -30
  318. data/lib/webgen/sourcehandler/feed.rb +0 -92
  319. data/lib/webgen/sourcehandler/fragment.rb +0 -70
  320. data/lib/webgen/sourcehandler/memory.rb +0 -42
  321. data/lib/webgen/sourcehandler/metainfo.rb +0 -128
  322. data/lib/webgen/sourcehandler/page.rb +0 -64
  323. data/lib/webgen/sourcehandler/sitemap.rb +0 -60
  324. data/lib/webgen/sourcehandler/template.rb +0 -66
  325. data/lib/webgen/sourcehandler/virtual.rb +0 -117
  326. data/lib/webgen/tag/base.rb +0 -170
  327. data/lib/webgen/tag/breadcrumbtrail.rb +0 -70
  328. data/lib/webgen/tag/executecommand.rb +0 -31
  329. data/lib/webgen/tag/includefile.rb +0 -42
  330. data/lib/webgen/tag/metainfo.rb +0 -27
  331. data/lib/webgen/tag/sitemap.rb +0 -41
  332. data/lib/webgen/websiteaccess.rb +0 -31
  333. data/lib/webgen/websitemanager.rb +0 -125
  334. data/misc/default.css +0 -403
  335. data/misc/default.template +0 -76
  336. data/misc/htmldoc.metainfo +0 -26
  337. data/misc/htmldoc.virtual +0 -17
  338. data/misc/images/arrow.gif +0 -0
  339. data/misc/images/error.png +0 -0
  340. data/misc/images/headerbg.jpg +0 -0
  341. data/misc/images/important.png +0 -0
  342. data/misc/images/information.png +0 -0
  343. data/misc/images/quote.gif +0 -0
  344. data/misc/images/warning.png +0 -0
  345. data/misc/logo.svg +0 -313
  346. data/misc/style.page +0 -33
  347. data/test/helper.rb +0 -61
  348. data/test/test_blackboard.rb +0 -60
  349. data/test/test_cli.rb +0 -119
  350. data/test/test_common_sitemap.rb +0 -58
  351. data/test/test_configuration.rb +0 -68
  352. data/test/test_contentprocessor.rb +0 -39
  353. data/test/test_contentprocessor_builder.rb +0 -41
  354. data/test/test_contentprocessor_erb.rb +0 -33
  355. data/test/test_contentprocessor_erubis.rb +0 -62
  356. data/test/test_contentprocessor_fragments.rb +0 -43
  357. data/test/test_contentprocessor_haml.rb +0 -39
  358. data/test/test_contentprocessor_head.rb +0 -96
  359. data/test/test_contentprocessor_kramdown.rb +0 -56
  360. data/test/test_contentprocessor_less.rb +0 -40
  361. data/test/test_contentprocessor_maruku.rb +0 -33
  362. data/test/test_contentprocessor_rdiscount.rb +0 -21
  363. data/test/test_contentprocessor_rdoc.rb +0 -22
  364. data/test/test_contentprocessor_redcloth.rb +0 -26
  365. data/test/test_contentprocessor_sass.rb +0 -28
  366. data/test/test_contentprocessor_scss.rb +0 -28
  367. data/test/test_contentprocessor_tags.rb +0 -122
  368. data/test/test_contentprocessor_tidy.rb +0 -34
  369. data/test/test_contentprocessor_xmllint.rb +0 -38
  370. data/test/test_context.rb +0 -81
  371. data/test/test_error.rb +0 -93
  372. data/test/test_loggable.rb +0 -32
  373. data/test/test_logger.rb +0 -94
  374. data/test/test_node.rb +0 -469
  375. data/test/test_output_filesystem.rb +0 -60
  376. data/test/test_path.rb +0 -241
  377. data/test/test_source_filesystem.rb +0 -76
  378. data/test/test_source_resource.rb +0 -28
  379. data/test/test_source_stacked.rb +0 -49
  380. data/test/test_sourcehandler_base.rb +0 -136
  381. data/test/test_sourcehandler_copy.rb +0 -47
  382. data/test/test_sourcehandler_directory.rb +0 -38
  383. data/test/test_sourcehandler_feed.rb +0 -88
  384. data/test/test_sourcehandler_fragment.rb +0 -70
  385. data/test/test_sourcehandler_main.rb +0 -39
  386. data/test/test_sourcehandler_memory.rb +0 -44
  387. data/test/test_sourcehandler_metainfo.rb +0 -127
  388. data/test/test_sourcehandler_page.rb +0 -73
  389. data/test/test_sourcehandler_sitemap.rb +0 -68
  390. data/test/test_sourcehandler_template.rb +0 -68
  391. data/test/test_sourcehandler_virtual.rb +0 -106
  392. data/test/test_tag_base.rb +0 -62
  393. data/test/test_tag_breadcrumbtrail.rb +0 -91
  394. data/test/test_tag_coderay.rb +0 -45
  395. data/test/test_tag_date.rb +0 -18
  396. data/test/test_tag_executecommand.rb +0 -41
  397. data/test/test_tag_includefile.rb +0 -50
  398. data/test/test_tag_langbar.rb +0 -71
  399. data/test/test_tag_link.rb +0 -70
  400. data/test/test_tag_menu.rb +0 -207
  401. data/test/test_tag_metainfo.rb +0 -26
  402. data/test/test_tag_relocatable.rb +0 -60
  403. data/test/test_tag_sitemap.rb +0 -47
  404. data/test/test_tag_tikz.rb +0 -69
  405. data/test/test_tree.rb +0 -70
  406. data/test/test_website.rb +0 -130
  407. data/test/test_websiteaccess.rb +0 -25
  408. data/test/test_websitemanager.rb +0 -65
@@ -0,0 +1,63 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'webgen/cli/utils'
4
+
5
+ module Webgen
6
+ module CLI
7
+
8
+ # The CLI command for showing all available options.
9
+ class ShowConfigCommand < CmdParse::Command
10
+
11
+ def initialize # :nodoc:
12
+ super('config', false, false, true)
13
+ self.short_desc = 'Show available configuration options'
14
+ self.description = Utils.format_command_desc(<<DESC)
15
+ Shows all available configuration options. The option name and default value as
16
+ well as the currently used value are displayed.
17
+
18
+ If the global verbosity option is set, option descriptions are additionally
19
+ displayed.
20
+
21
+ If an argument is given, only those options that have the argument in their name
22
+ are displayed.
23
+
24
+ Hint: A debug message will appear at the top of the output if this command is run
25
+ in the context of a website, there are unknown configuration options in the
26
+ configuration file and the log level is set to debug.
27
+ DESC
28
+ self.options = CmdParse::OptionParserWrapper.new do |opts|
29
+ opts.separator "Options:"
30
+ opts.on("-m", "--modified",
31
+ *Utils.format_option_desc("Show modified configuration options only")) do |v|
32
+ @modified = true
33
+ end
34
+ end
35
+ @modified = false
36
+ @unknown = true
37
+ end
38
+
39
+ def execute(args) # :nodoc:
40
+ config = commandparser.website.config
41
+ selector = args.first.to_s
42
+ config.options.select do |n, d|
43
+ n.include?(selector) && (!@modified || config[n] != d.default)
44
+ end.sort.each do |name, data|
45
+ format_config_option(name, data, config[name])
46
+ end
47
+ end
48
+
49
+ def format_config_option(name, data, cur_val)
50
+ print("#{Utils.light(Utils.blue(name))}: ")
51
+ if cur_val != data.default
52
+ puts(Utils.green(cur_val.to_s) + " (default: #{data.default})")
53
+ else
54
+ puts(cur_val.inspect)
55
+ end
56
+ puts(Utils.format(data.description, 78, 2, true).join("\n") + "\n\n") if commandparser.verbose
57
+ end
58
+ private :format_config_option
59
+
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,103 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'webgen/cli/utils'
4
+
5
+ module Webgen
6
+ module CLI
7
+
8
+ # The CLI command for showing dependencies (tracked items) of paths.
9
+ class ShowDependenciesCommand < CmdParse::Command
10
+
11
+ def initialize # :nodoc:
12
+ super('deps', false, false, true)
13
+ self.short_desc = 'Show dependencies for all paths'
14
+ self.description = Utils.format_command_desc(<<DESC)
15
+ Shows the dependencies (i.e. tracked items) for each path. This is only useful
16
+ after webgen has generated the website at least once so that this information
17
+ is available.
18
+
19
+ If an argument is given, only those paths that have the argument in their name
20
+ are displayed with their dependencies.
21
+
22
+ Hint: The global verbosity option enables additional output.
23
+ DESC
24
+ end
25
+
26
+ def execute(args) # :nodoc:
27
+ cache = commandparser.website.cache[:item_tracker_data]
28
+ if cache.nil?
29
+ puts "No data available, you need to generate the website first!"
30
+ return
31
+ end
32
+ arg = args.shift
33
+
34
+ data = cache[:node_dependencies]
35
+ data = data.select {|alcn, _| alcn.include?(arg) } if arg
36
+ data.sort.each do |alcn, deps|
37
+ deps = deps.sort {|a,b| a.first <=> b.first }.map do |uid|
38
+ method = "format_#{uid.first}"
39
+ if respond_to?(method, true)
40
+ send(method, alcn, uid, cache[:item_data][uid])
41
+ else
42
+ unknown_uid(uid)
43
+ end
44
+ end.compact
45
+
46
+ if deps.length > 0 || commandparser.verbose
47
+ puts("#{Utils.light(Utils.blue(alcn))}: ")
48
+ deps.each {|d| puts(" #{[d].flatten.join("\n ")}")}
49
+ end
50
+ end
51
+ end
52
+
53
+ def unknown_uid(uid)
54
+ uid.first.to_s
55
+ end
56
+ private :unknown_uid
57
+
58
+ def format_node_meta_info(alcn, uid, data)
59
+ dep_alcn, key = *uid.last
60
+ return if alcn == dep_alcn && !commandparser.verbose
61
+
62
+ if key.nil?
63
+ "Any meta info from <#{dep_alcn}>"
64
+ else
65
+ "Meta info key '#{key}' from <#{dep_alcn}>"
66
+ end
67
+ end
68
+ private :format_node_meta_info
69
+
70
+ def format_node_content(alcn, uid, data)
71
+ dep_alcn = uid.last
72
+ return if alcn == dep_alcn && !commandparser.verbose
73
+
74
+ "Content from node <#{dep_alcn}>"
75
+ end
76
+ private :format_node_content
77
+
78
+ def format_file(alcn, uid, data)
79
+ "Content from file '#{uid.last}'"
80
+ end
81
+ private :format_file
82
+
83
+ def format_missing_node(alcn, uid, data)
84
+ path, lang = *uid.last
85
+
86
+ "Missing acn, alcn or dest path <#{path}>" << (lang.nil? ? '' : " in language '#{lang}'")
87
+ end
88
+ private :format_missing_node
89
+
90
+ def format_nodes(alcn, uid, data)
91
+ method, _, type = *uid.last
92
+
93
+ res = [(type == :content ? "Content" : "Meta info") + " from these nodes"]
94
+ res.first << " (result of #{[method].flatten.join('.')})" if commandparser.verbose
95
+ res.first << ":"
96
+ res += data.flatten
97
+ end
98
+ private :format_nodes
99
+
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,74 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'webgen/cli/utils'
4
+
5
+ module Webgen
6
+ module CLI
7
+
8
+ # The CLI command for showing available extension.
9
+ class ShowExtensionsCommand < CmdParse::Command
10
+
11
+ def initialize # :nodoc:
12
+ super('extensions', false, false, true)
13
+ self.short_desc = 'Show available extensions'
14
+ self.description = Utils.format_command_desc(<<DESC)
15
+ Shows all available extensions and additional information about them, e.g. a
16
+ short summary of the functionality or the extension bundle it is defined in.
17
+
18
+ If an argument is given, only those extensions that have the argument in their
19
+ name are displayed.
20
+
21
+ Hint: The global verbosity option enables additional output.
22
+ DESC
23
+ self.options = CmdParse::OptionParserWrapper.new do |opts|
24
+ opts.separator "Options:"
25
+ opts.on("-b NAME", "--bundle NAME", String,
26
+ *Utils.format_option_desc("Only show extensions of this bundle")) do |bundle|
27
+ @bundle = bundle
28
+ end
29
+ end
30
+ @bundle = nil
31
+ end
32
+
33
+ def execute(args) # :nodoc:
34
+ exts = {}
35
+ commandparser.website.ext.bundles.each do |bundle, info_file|
36
+ next if info_file.nil? || (@bundle && @bundle != bundle)
37
+ infos = YAML.load(File.read(info_file))
38
+ next unless infos['extensions']
39
+ infos['extensions'].each do |n, d|
40
+ d['bundle'] = bundle
41
+ d['author'] ||= infos['author']
42
+ end
43
+ exts.update(infos['extensions'])
44
+ end
45
+
46
+ selector = args.first.to_s
47
+ exts.select {|n, d| n.include?(selector)}.sort.each do |name, data|
48
+ format_extension_info(name, data, !selector.empty?)
49
+ end
50
+ end
51
+
52
+ def format_extension_info(name, data, has_selector)
53
+ author = (!data['author'] || data['author'].empty? ? 'unknown' : data['author'])
54
+
55
+ indentation = (has_selector ? 0 : name.count('.')*2)
56
+ puts(" "*indentation + Utils.light(Utils.blue(name)))
57
+ if commandparser.verbose
58
+ print(" "*(indentation + 2) + "Bundle: ")
59
+ puts(Utils.format(data['bundle'], 78, indentation + 11, false))
60
+ print(" "*(indentation + 2) + "Author: ")
61
+ puts(Utils.format(author, 78, indentation + 11, false))
62
+ print(" "*(indentation + 2) + "Summary: ")
63
+ puts(Utils.format(data['summary'], 78, indentation + 11, false))
64
+ else
65
+ puts(Utils.format(data['summary'], 78, indentation + 2, true).join("\n"))
66
+ end
67
+ puts
68
+ end
69
+ private :format_extension_info
70
+
71
+ end
72
+
73
+ end
74
+ end
@@ -2,119 +2,92 @@
2
2
 
3
3
  require 'rbconfig'
4
4
 
5
- module Webgen::CLI
5
+ module Webgen
6
6
 
7
- # Provides methods for other CLI classes for formatting text in a consistent manner.
8
- class Utils
7
+ module CLI
9
8
 
10
- USE_ANSI_COLORS = Config::CONFIG['host_os'] !~ /mswin|mingw/
11
- DEFAULT_WIDTH = if Config::CONFIG['host_os'] =~ /mswin|mingw/
12
- 72
13
- else
14
- ((size = %x{stty size 2>/dev/null}).length > 0 && (size = size.split.last.to_i) > 0 ? size : 72) rescue 72
15
- end
9
+ # Provides methods for CLI classes for formatting text in a consistent manner.
10
+ module Utils
16
11
 
17
- module Color
12
+ class << self; attr_accessor :use_colors; end
13
+ @use_colors = $stdout.tty? && RbConfig::CONFIG['host_os'] !~ /mswin|mingw/
18
14
 
19
- @@colors = {:bold => [0, 1], :green => [0, 32], :lred => [1, 31], :reset => [0, 0]}
15
+ DEFAULT_WIDTH = 80
20
16
 
21
- @@colors.each do |color, values|
22
- module_eval <<-EOF
23
- def Color.#{color.to_s}(text = nil)
24
- "\e[#{values[0]};#{values[1]}m" + (text.nil? ? '' : text + self.reset)
25
- end
26
- EOF
27
- end
17
+ module Color # :nodoc:
28
18
 
29
- end
19
+ @@colors = {:bold => [1], :light => [1], :green => [32], :yellow => [33], :red => [31], :blue => [34], :reset => [0]}
30
20
 
21
+ @@colors.each do |color, values|
22
+ module_eval("def Color.#{color.to_s}(text = nil);" <<
23
+ "'\e[#{values.join(';')}m' << (text.nil? ? '' : text + self.reset); end")
24
+ end
31
25
 
32
- # Used for dynamically formatting the text (setting color, bold face, ...).
33
- def self.method_missing(id, text = nil)
34
- if USE_ANSI_COLORS && Color.respond_to?(id)
35
- Color.send(id, text.to_s)
36
- else
37
- text.to_s
38
26
  end
39
- end
40
27
 
41
- # Return an array of lines which represents the text in +content+ formatted sothat no line is
42
- # longer than +width+ characters. The +indent+ parameter specifies the amount of spaces
43
- # prepended to each line. If +first_line_indented+ is +true+, then the first line is indented.
44
- def self.format(content, indent = 0, first_line_indented = false, width = DEFAULT_WIDTH)
45
- content = (content || '').dup
46
- length = width - indent
47
-
48
- paragraphs = content.split(/\n\n/)
49
- if (0..1) === paragraphs.length
50
- pattern = /^(.{0,#{length}})[ \n]/m
51
- lines = []
52
- while content.length > length
53
- if content =~ pattern
54
- str = $1
55
- len = $&.length
56
- else
57
- str = content[0, length]
58
- len = length
59
- end
60
- lines << (lines.empty? && !first_line_indented ? '' : ' '*indent) + str.gsub(/\n/, ' ')
61
- content.slice!(0, len)
28
+
29
+ # Used for dynamically formatting the text (setting color, bold face, ...).
30
+ #
31
+ # The +id+ (method name) can be one of the following: bold, light, green, yellow, red, blue,
32
+ # reset.
33
+ def self.method_missing(id, text = nil)
34
+ if self.use_colors && Color.respond_to?(id)
35
+ Color.send(id, text)
36
+ else
37
+ text.to_s
62
38
  end
63
- lines << (lines.empty? && !first_line_indented ? '' : ' '*indent) + content.gsub(/\n/, ' ') unless content.strip.empty?
64
- lines
65
- else
66
- ((format(paragraphs.shift, indent, first_line_indented, width) << '') +
67
- paragraphs.collect {|p| format(p, indent, true, width) << '' }).flatten[0..-2]
68
39
  end
69
- end
70
40
 
71
- # Return a headline with the given +text+ and amount of +indent+.
72
- def self.headline(text, indent = 2)
73
- ' '*indent + "#{bold(text)}"
74
- end
75
-
76
- # Return a section header with the given +text+ formatted in the given +color+ and indented
77
- # according to +indent+. The whole text is also left justified to the column specified with
78
- # +ljustlength+.
79
- def self.section(text, ljustlength = 0, indent = 4, color = :green)
80
- ' '*indent + "#{send(color, text)}".ljust(ljustlength - indent + send(color).length)
81
- end
82
-
83
- # Creates a listing of the key-value pairs of +hash+ under a section called +name+.
84
- def self.hash_output(name, hash)
85
- ljust = 20
86
- puts section('Name', ljust) + "#{lred(name)}"
41
+ # Format the command description.
42
+ #
43
+ # Returns an array of Strings.
44
+ #
45
+ # See Utils.format for more information.
46
+ def self.format_command_desc(desc)
47
+ format(desc, 76)
48
+ end
87
49
 
88
- hash.sort_by {|k,v| k.to_s }.each do |name, value|
89
- next unless value.respond_to?(:to_str)
90
- desc = format(value.to_str, ljust)
91
- puts section(name.to_s.capitalize, ljust) + desc.shift
92
- desc.each {|line| puts line}
50
+ # Format the option description.
51
+ #
52
+ # Returns an array of Strings.
53
+ #
54
+ # See Utils.format for more information.
55
+ def self.format_option_desc(desc)
56
+ format(desc, 48)
93
57
  end
94
- puts
95
- end
96
58
 
97
- # Tries to match +name+ to a unique bundle name of the WebsiteManager +wm+. If this can not be
98
- # done, it is checked whether +name+ is actually a valid bundle URL and if so, the URL source is
99
- # added to the bundles of +wm+.
100
- #
101
- # Returns the correct bundle name or raises an error.
102
- def self.match_bundle_name(wm, name)
103
- matches = wm.bundles.keys.select {|k| k =~ /#{Regexp.escape(name)}/}
104
- if matches.size > 1
105
- raise ArgumentError.new("#{name} matches more than one bundle: #{matches.join(", ")}")
106
- elsif matches.size == 0
107
- begin
108
- source = Webgen::Source::TarArchive.new(name)
109
- wm.add_source(source, 'custom-URL-source')
110
- name = 'custom-URL-source'
111
- rescue
112
- raise ArgumentError.new("#{name} is neither a valid bundle name nor a valid URL")
59
+ # Return an array of lines which represents the text in +content+ formatted so that no line is
60
+ # longer than +width+ characters.
61
+ #
62
+ # The +indent+ parameter specifies the amount of spaces prepended to each line. If
63
+ # +first_line_indented+ is +true+, then the first line is indented.
64
+ def self.format(content, width = DEFAULT_WIDTH, indent = 0, first_line_indented = false)
65
+ content = (content || '').dup
66
+ length = width - indent
67
+
68
+ paragraphs = content.split(/\n\n/)
69
+ if (0..1) === paragraphs.length
70
+ pattern = /^(.{0,#{length}})[ \n]/m
71
+ lines = []
72
+ while content.length > length
73
+ if content =~ pattern
74
+ str = $1
75
+ len = $&.length
76
+ else
77
+ str = content[0, length]
78
+ len = length
79
+ end
80
+ lines << (lines.empty? && !first_line_indented ? '' : ' '*indent) + str.gsub(/\n/, ' ')
81
+ content.slice!(0, len)
82
+ end
83
+ lines << (lines.empty? && !first_line_indented ? '' : ' '*indent) + content.gsub(/\n/, ' ') unless content.strip.empty?
84
+ lines
85
+ else
86
+ ((format(paragraphs.shift, width, indent, first_line_indented) << '') +
87
+ paragraphs.collect {|p| format(p, width, indent, true) << '' }).flatten[0..-2]
113
88
  end
114
- else
115
- name = matches.first
116
89
  end
117
- name
90
+
118
91
  end
119
92
 
120
93
  end
@@ -1,149 +1,187 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
+ require 'yaml'
4
+ require 'webgen/error'
5
+
3
6
  module Webgen
4
7
 
5
8
  # Stores the configuration for a webgen website.
6
9
  #
7
- # Configuration options should be created like this:
10
+ # Configuration options can be created by using the define_option method:
11
+ #
12
+ # config.define_option "my.new.option", 'default value', 'description'
13
+ #
14
+ # and later accessed or set using the accessor methods #[] and #[]=. A validation block can also
15
+ # be specified when defining an option. This validation block is called when a new value should be
16
+ # set and it should return the (possibly changed) value to be set:
8
17
  #
9
- # config.my.new.config 'value', :doc => 'some', :meta => 'info'
18
+ # config.define_option "my.new.option", 'default value', 'description' do |val|
19
+ # raise "Option must be a string" unless val.kind_of?(String)
20
+ # val.upcase
21
+ # end
10
22
  #
11
- # and later accessed or set using the accessor methods #[] and #[]= or a configuration helper.
12
- # These helpers are defined in the Helpers module and provide easier access to complex
13
- # configuration options. Also see the {webgen
14
- # manual}[http://webgen.rubyforge.org/documentation/manual.html#website-configfile] for
15
- # information about the configuration helpers.
23
+ # **Note**: When a Configuration object is dumped (via Marshal), the option validator procs are
24
+ # not dumped and can therefore not be restored.
16
25
  class Configuration
17
26
 
18
- # Helper class for providing an easy method to define configuration options.
19
- class MethodChain
27
+ # Raised by the Webgen::Configuration class.
28
+ class Error < Webgen::Error; end
20
29
 
21
- def initialize(config) #:nodoc:
22
- @config = config
23
- @name = ''
30
+ # Struct class for storing a configuration option.
31
+ Option = Struct.new(:default, :description, :validator) do
32
+ def dupped_default #:nodoc:
33
+ default.dup rescue default
24
34
  end
25
35
 
26
- def method_missing(id, *args) #:nodoc:
27
- @name += (@name.empty? ? '' : '.') + id.id2name.sub(/(!|=)$/,'')
28
- if args.length > 0
29
- value = args.shift
30
- @config.data[@name] = value unless @config.data.has_key?(@name) # value is set only the first time
31
- @config.meta_info[@name] ||= {}
32
- @config.meta_info[@name].update(*args) if args.length > 0
33
- nil
34
- else
35
- self
36
- end
36
+ def ==(other) #:nodoc:
37
+ self.default == other.default
37
38
  end
38
39
 
39
- end
40
-
41
- # This module provides methods for setting more complex configuration options. It is mixed into
42
- # Webgen::Configuration so that its methods can be used. Detailed information on the use of the
43
- # methods can be found in the "User Manual" in the "Configuration File" section.
44
- #
45
- # All public methods defined in this module are available for direct use in the
46
- # configuration file, e.g. the method named +default_meta_info+ can be used like this:
47
- #
48
- # default_meta_info:
49
- # Webgen::SourceHandler::Page:
50
- # in_menu : true
51
- # :action : replace
52
- #
53
- # All methods have to take exactly one argument, a Hash.
54
- #
55
- # The special key <tt>:action</tt> should be used for specifying how the configuration option
56
- # should be set:
57
- #
58
- # [replace] Replace the configuration option with the new values.
59
- # [modify] Replace old values with new values and add missing ones (useful for hashes and
60
- # normally the default value)
61
- module Helpers
62
-
63
- # Set the default meta information for source handlers.
64
- def default_meta_info(args)
65
- args.each do |sh_name, mi|
66
- raise ArgumentError, 'Invalid argument for configuration helper default_meta_info' unless mi.kind_of?(Hash)
67
- action = mi.delete(:action) || 'modify'
68
- mi_hash = (self['sourcehandler.default_meta_info'][complete_source_handler_name(sh_name)] ||= {})
69
- case action
70
- when 'replace' then mi_hash.replace(mi)
71
- else mi_hash.update(mi)
72
- end
73
- end
40
+ def marshal_dump #:nodoc:
41
+ [self.default, self.description]
74
42
  end
75
43
 
76
-
77
- # Set the path patterns used by source handlers.
78
- def patterns(args)
79
- args.each do |sh_name, data|
80
- pattern_arr = (self['sourcehandler.patterns'][complete_source_handler_name(sh_name)] ||= [])
81
- case data
82
- when Array then pattern_arr.replace(data)
83
- when Hash
84
- (data['del'] || []).each {|pat| pattern_arr.delete(pat)}
85
- (data['add'] || []).each {|pat| pattern_arr << pat}
86
- else
87
- raise ArgumentError, 'Invalid argument for configuration helper patterns'
88
- end
89
- end
44
+ def marshal_load(data) #:nodoc:
45
+ self.default = data[0]
46
+ self.description = data[1]
90
47
  end
91
48
 
49
+ end
92
50
 
93
- # Set the default processing pipeline for a source handler.
94
- def default_processing_pipeline(args)
95
- args.each do |sh_name, pipeline|
96
- raise ArgumentError, 'Invalid argument for configuration helper pipeline' unless pipeline.kind_of?(String)
97
- mi_hash = (self['sourcehandler.default_meta_info'][complete_source_handler_name(sh_name)] ||= {})
98
- ((mi_hash['blocks'] ||= {})['default'] ||= {})['pipeline'] = pipeline
99
- end
100
- end
101
51
 
52
+ # Contains all the defined configuration options.
53
+ attr_reader :options
102
54
 
103
- # Complete +sh_name+ by checking if a source handler called
104
- # <tt>Webgen::SourceHandler::SH_NAME</tt> exists.
105
- def complete_source_handler_name(sh_name)
106
- (Webgen::SourceHandler.constants.map {|c| c.to_s}.include?(sh_name) ? 'Webgen::SourceHandler::' + sh_name : sh_name)
107
- end
108
- private :complete_source_handler_name
55
+ # Create a new Configuration object.
56
+ def initialize
57
+ @options = {}
58
+ @values = {}
59
+ end
109
60
 
61
+ def initialize_copy(orig) #:nodoc:
62
+ super
63
+ @options = orig.options.dup
64
+ @values = {}
65
+ orig.instance_eval { @values }.each {|k,v| @values[k] = v.dup rescue v}
110
66
  end
111
67
 
68
+ def clone #:nodoc:
69
+ super
70
+ freeze if frozen?
71
+ end
112
72
 
113
- include Helpers
73
+ def freeze #:nodoc:
74
+ super
75
+ @options.freeze
76
+ @values.each_value {|v| v.freeze}
77
+ @values.freeze
78
+ self
79
+ end
114
80
 
115
- # The hash which stores the meta info for the configuration options.
116
- attr_reader :meta_info
81
+ def ==(other) #:nodoc:
82
+ @options == other.options && @values == other.instance_variable_get(:@values)
83
+ end
117
84
 
118
- # The configuration options hash.
119
- attr_reader :data
85
+ # Define a new option +name+ with a default value of +default+ and the description.
86
+ #
87
+ # If a validation block is provided, it is called with the new value when one is set and should
88
+ # return a (possibly altered) value to be set.
89
+ def define_option(name, default, description, &validator)
90
+ if @options.has_key?(name)
91
+ raise ArgumentError, "Configuration option '#{name}' has already be defined"
92
+ else
93
+ @options[name] = Option.new
94
+ @options[name].default = default.freeze
95
+ @options[name].description = description.freeze
96
+ @options[name].validator = validator.freeze
97
+ @options[name].freeze
98
+ end
99
+ end
120
100
 
121
- # Create a new Configuration object.
122
- def initialize
123
- @data = {}
124
- @meta_info = {}
101
+ # Return +true+ if the given option exists.
102
+ def option?(name)
103
+ @options.has_key?(name)
125
104
  end
126
105
 
127
- # Return the configuration option +name+.
106
+ # Return the value for the configuration option +name+.
128
107
  def [](name)
129
- if @data.has_key?(name)
130
- @data[name]
108
+ if @options.has_key?(name)
109
+ if frozen?
110
+ @values.has_key?(name) ? @values[name] : @options[name].dupped_default
111
+ else
112
+ @values[name] = @options[name].dupped_default unless @values.has_key?(name)
113
+ @values[name]
114
+ end
131
115
  else
132
- raise ArgumentError, "No such configuration option: #{name}"
116
+ raise Error, "Configuration option '#{name}' does not exist"
133
117
  end
134
118
  end
135
119
 
136
- # Set the configuration option +name+ to the provided +value+.
120
+ # Use +value+ as value for the configuration option +name+.
137
121
  def []=(name, value)
138
- if @data.has_key?(name)
139
- @data[name] = value
122
+ if @options.has_key?(name)
123
+ begin
124
+ @values[name] = (@options[name].validator ? @options[name].validator.call(value) : value)
125
+ rescue
126
+ raise Error, "Problem setting configuration option '#{name}': #{$!.message}", $!.backtrace
127
+ end
140
128
  else
141
- raise ArgumentError, "No such configuration option: #{name}"
129
+ raise Error, "Configuration option '#{name}' does not exist"
142
130
  end
143
131
  end
144
132
 
145
- def method_missing(id, *args) #:nodoc:
146
- MethodChain.new(self).method_missing(id, *args)
133
+ # Set the configuration values from the Hash +values+.
134
+ #
135
+ # The hash can either contain full configuration option names or namespaced option names, ie. in
136
+ # YAML format:
137
+ #
138
+ # my.option: value
139
+ #
140
+ # website:
141
+ # lang: en
142
+ # url: my_url
143
+ #
144
+ # The above hash will set the option 'my.option' to +value+, 'website.lang' to +en+ and
145
+ # 'website.url' to +my_url+.
146
+ #
147
+ # Returns an array with all unknown configuration options.
148
+ def set_values(values)
149
+ unknown_options = []
150
+ process = proc do |name, value|
151
+ if @options.has_key?(name)
152
+ self[name] = value
153
+ elsif value.kind_of?(Hash)
154
+ value.each {|k,v| process.call("#{name}.#{k}", v)}
155
+ else
156
+ unknown_options << name
157
+ end
158
+ end
159
+ values.each(&process)
160
+ unknown_options
161
+ end
162
+
163
+ # Load the configuration values.
164
+ #
165
+ # If +filename+ is a String, it is treated as the name of the configuration file from which the
166
+ # values should be loaded. If +filename+ responds to \#read, it is treated as an IO object from
167
+ # which the values should be loaded.
168
+ #
169
+ # The configuration needs to be in YAML format. More specifically, it needs to contain a YAML
170
+ # hash which is further processed by #set_values.
171
+ #
172
+ # Returns an array with all unknown configuration options.
173
+ def load_from_file(filename)
174
+ data = if String === filename || filename.respond_to?(:read)
175
+ begin
176
+ YAML::load(String === filename ? File.read(filename) : filename.read) || {}
177
+ rescue RuntimeError, ArgumentError, SyntaxError => e
178
+ raise Error, "Problem parsing configuration data (it needs to contain a YAML hash): #{e.message}", e.backtrace
179
+ end
180
+ else
181
+ raise ArgumentError, "Need a String or IO object, not a #{filename.class}"
182
+ end
183
+ raise Error, 'Structure of configuration file is invalid, it has to be a Hash' unless data.kind_of?(Hash)
184
+ set_values(data)
147
185
  end
148
186
 
149
187
  end