webgen 0.5.17 → 1.0.0.beta1

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 (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,40 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'webgen/item_tracker'
4
+
5
+ module Webgen
6
+ class ItemTracker
7
+
8
+ # This class is used to track changes to the content of a node. The content of a node is changed
9
+ # if any of its dependencies are changed.
10
+ #
11
+ # The item for this tracker is the alcn of the node:
12
+ #
13
+ # website.ext.item_tracker.add(some_node, :node_content, my_node.alcn)
14
+ #
15
+ class NodeContent
16
+
17
+ def initialize(website) #:nodoc:
18
+ @website = website
19
+ end
20
+
21
+ def item_id(alcn) #:nodoc:
22
+ alcn
23
+ end
24
+
25
+ def item_data(alcn) #:nodoc:
26
+ nil
27
+ end
28
+
29
+ def changed?(alcn, old_data) #:nodoc:
30
+ @website.tree[alcn].nil? || @website.ext.item_tracker.node_changed?(@website.tree[alcn])
31
+ end
32
+
33
+ def node_referenced?(alcn, nothing, node_alcn) #:nodoc:
34
+ alcn == node_alcn
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,53 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'webgen/item_tracker'
4
+
5
+ module Webgen
6
+ class ItemTracker
7
+
8
+ # This class is used to track changes to a node's meta information.
9
+ #
10
+ # Depending on what should be tracked, one needs to provide the following item:
11
+ #
12
+ # [node_alcn, nil]
13
+ # Tracks changes to the whole meta information of the node, i.e. if any meta information value
14
+ # changes, a change is detected.
15
+ #
16
+ # [node_alcn, key]
17
+ # Tracks changes to a specific meta information key of the node.
18
+ #
19
+ # Here are some examples:
20
+ #
21
+ # website.ext.item_tracker.add(some_node, :node_meta_info, my_node.alcn) # first case
22
+ # website.ext.item_tracker.add(some_node, :node_meta_info, my_node.alcn, 'title') # second case
23
+ #
24
+ class NodeMetaInfo
25
+
26
+ CONTENT_MODIFICATION_KEY = 'modified_at'
27
+
28
+ def initialize(website) #:nodoc:
29
+ @website = website
30
+ end
31
+
32
+ def item_id(alcn, key = nil) #:nodoc:
33
+ [alcn, key]
34
+ end
35
+
36
+ def item_data(alcn, key = nil) #:nodoc:
37
+ mi = @website.tree[alcn].meta_info
38
+ key.nil? ? (mi = mi.dup; mi.delete(CONTENT_MODIFICATION_KEY); mi) : mi[key].dup
39
+ end
40
+
41
+ def changed?(iid, old_data) #:nodoc:
42
+ alcn, key = *iid
43
+ @website.tree[alcn].nil? || item_data(alcn, key) != old_data
44
+ end
45
+
46
+ def node_referenced?(iid, mi, node_alcn) #:nodoc:
47
+ iid.first == node_alcn
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,92 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'webgen/item_tracker'
4
+
5
+ module Webgen
6
+ class ItemTracker
7
+
8
+ # This class is used to track changes to a (nested) list of nodes.
9
+ #
10
+ # An item for this tracker has to consist of the following fields:
11
+ #
12
+ # * An array consisting of [class/module name, method name] or a string/symbol specifying a
13
+ # method name
14
+ # * Options argument (use an array or hash for multiple arguments)
15
+ # * Either :content or :meta_info, depending on whether the content or the meta info of
16
+ # the found nodes should be tracked.
17
+ #
18
+ # The list of nodes is retrieved in one of two ways, depending on the type of the first field:
19
+ #
20
+ # * If it is a string/symbol, it specifies the name of a method on this class. This method has
21
+ # to take the options hash as the only parameter.
22
+ #
23
+ # * If it is an array, the array has to contain a class/module name and a method name. The
24
+ # method is invoked with the current Webgen::Website object as first and the options hash as
25
+ # second parameter.
26
+ #
27
+ # For example, consider the following statement:
28
+ #
29
+ # website.ext.item_tracker.add(some_node, :nodes,
30
+ # ["MyModule::MyClass", "my_method"], {:some => 'options'}, :content)
31
+ #
32
+ # The method will be invoked like this for retrieving the nodes:
33
+ #
34
+ # MyModule::MyClass.my_method(website, {:some => 'options'})
35
+ #
36
+ class Nodes
37
+
38
+ def initialize(website) #:nodoc:
39
+ @website = website
40
+ end
41
+
42
+ def item_id(method_name, options, type) #:nodoc:
43
+ [method_name, options, type]
44
+ end
45
+
46
+ def item_data(method_name, options, type) #:nodoc:
47
+ nodes_to_alcn(node_list(method_name, options))
48
+ end
49
+
50
+ def changed?(iid, old_data) #:nodoc:
51
+ method_name, options, type = *iid
52
+ nodes = node_list(method_name, options)
53
+ old_data != nodes_to_alcn(nodes) ||
54
+ nodes.flatten.any? {|n| type == :content ? @website.ext.item_tracker.node_changed?(n) : @website.ext.item_tracker.item_changed?(:node_meta_info, n.alcn)}
55
+ end
56
+
57
+ def node_referenced?(iid, alcn_list, node_alcn) #:nodoc:
58
+ alcn_list.flatten.any? {|alcn| alcn == node_alcn}
59
+ end
60
+
61
+ # Use Webgen::NodeFinder to generate a (nested) list of nodes. The options hash has to contain
62
+ # two keys:
63
+ #
64
+ # * :opts → the node finder option set
65
+ # * :ref_alcn → the alcn of the reference node
66
+ #
67
+ def node_finder_option_set(options)
68
+ @website.ext.node_finder.find(options[:opts], @website.tree[options[:ref_alcn]])
69
+ end
70
+
71
+ # Return the list of nodes.
72
+ def node_list(method_name, options)
73
+ if method_name.kind_of?(Array)
74
+ Webgen::Utils.const_for_name(method_name.first).send(method_name.last, @website, options)
75
+ else
76
+ send(method_name, options)
77
+ end
78
+ rescue Exception
79
+ []
80
+ end
81
+ private :node_list
82
+
83
+ # Map the (nested) list of nodes to a (nested) list of alcn.
84
+ def nodes_to_alcn(nodes) #:nodoc:
85
+ nodes.map {|node, children| children.nil? ? node.alcn : [node.alcn, nodes_to_alcn(children)]}
86
+ end
87
+ private :nodes_to_alcn
88
+
89
+ end
90
+
91
+ end
92
+ end
data/lib/webgen/logger.rb CHANGED
@@ -1,97 +1,41 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
- require 'stringio'
4
3
  require 'logger'
5
4
 
6
5
  module Webgen
7
6
 
8
- # The class used by a Website to do the logging and the normal output.
9
- class Logger
10
-
11
- # Specifies whether log output should be synchronous with normal output.
12
- attr_reader :sync
13
-
14
- # Normal output verbosity (:normal, :verbose, :quiet).
15
- attr_accessor :verbosity
16
-
17
- # Create a new Logger object which uses +outdev+ as output device. If +sync+ is set to +true+,
18
- # log messages are interspersed with normal output.
19
- def initialize(outdev=$stdout, sync=false)
20
- @sync = sync
21
- @outdev = outdev
22
- @logger = (@sync ? ::Logger.new(@outdev) : ::Logger.new(@logio = StringIO.new))
23
- @logger.formatter = Proc.new do |severity, timestamp, progname, msg|
24
- if self.level == ::Logger::DEBUG
25
- "%5s -- %s: %s\n" % [severity, progname, msg ]
26
- else
27
- "%5s -- %s\n" % [severity, msg]
28
- end
29
- end
30
- self.level = ::Logger::WARN
31
- self.verbosity = :normal
32
- @marks = []
33
- end
34
-
35
- # Returns the output of the logger when #sync is +false+. Otherwise an empty string is returned.
36
- def log_output
37
- if @sync
38
- ''
39
- else
40
- out = @logio.string.dup
41
- @marks.reverse.each_with_index do |mark, index|
42
- out.insert(mark, " INFO -- Log messages for run #{@marks.length - index} are following\n")
43
- end if out.length > 0
44
- out
45
- end
46
- end
47
-
48
- # Only used when #sync is +false: Mark the location in the log stream where a new update/write
49
- # run begins.
50
- def mark_new_cycle
51
- if !@sync
52
- @marks << @logio.string.length
53
- end
7
+ # This custom logger class needs to be used (either directly or via a sub-class) for the
8
+ # Webgen::Website logging object.
9
+ #
10
+ # It provides the following, additional functionality over the stdlib Logger class:
11
+ #
12
+ # * If a logging message is an Array and #verbose is +false+, only the first item of the array is
13
+ # output. If #verbose is +true+, the the items of the array are joined using a line break and
14
+ # output.
15
+ #
16
+ # * You can add verbose info messages using the #vinfo method.
17
+ #
18
+ class Logger < ::Logger
19
+
20
+ # Whether verbose log message should be output. Either +true+ or +false+ (default: +false+).
21
+ attr_accessor :verbose
22
+
23
+ def initialize(*args, &block) #:nodoc:
24
+ super
25
+ @verbose = false
54
26
  end
55
27
 
56
- # The severity threshold level.
57
- def level
58
- @logger.level
28
+ def format_message(severity, datetime, progname, msg) #:nodoc:
29
+ first, *rest = *msg
30
+ msg = (@verbose ? [first, *rest].join("\n") : first)
31
+ super(severity, datetime, progname, msg)
59
32
  end
60
33
 
61
- # Set the severity threshold to +value+ which can be one of the stdlib Logger severity levels.
62
- def level=(value)
63
- @logger.level = value
34
+ # Log a verbose info message.
35
+ def vinfo(progname = nil, &block)
36
+ add(::Logger::INFO, nil, progname, &block) if @verbose
64
37
  end
65
38
 
66
- # Log a message of +sev_level+ from +source+. The mandatory block has to return the message.
67
- def log(sev_level, source='', &block)
68
- if sev_level == :stdout
69
- @outdev.write(block.call + "\n") if @verbosity == :normal || @verbosity == :verbose
70
- elsif sev_level == :verbose
71
- @outdev.write(block.call + "\n") if @verbosity == :verbose
72
- else
73
- @logger.send(sev_level, source, &block)
74
- end
75
- end
76
-
77
- # Utiltity method for logging an error message.
78
- def error(source='', &block); log(:error, source, &block); end
79
-
80
- # Utiltity method for logging a warning message.
81
- def warn(source='', &block); log(:warn, source, &block); end
82
-
83
- # Utiltity method for logging an informational message.
84
- def info(source='', &block); log(:info, source, &block); end
85
-
86
- # Utiltity method for logging a debug message.
87
- def debug(source='', &block); log(:debug, source, &block); end
88
-
89
- # Utiltity method for writing a normal output message.
90
- def stdout(source='', &block); log(:stdout, source, &block); end
91
-
92
- # Utiltity method for writing a verbose output message.
93
- def verbose(source='', &block); log(:verbose, source, &block); end
94
-
95
39
  end
96
40
 
97
41
  end
data/lib/webgen/node.rb CHANGED
@@ -1,27 +1,19 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
- require 'webgen/websiteaccess'
4
- require 'webgen/loggable'
5
- require 'webgen/path'
6
- require 'uri'
7
- require 'set'
8
3
  require 'pathname'
4
+ require 'webgen/languages'
5
+ require 'webgen/path'
9
6
 
10
7
  module Webgen
11
8
 
12
9
  # Represents a file, a directory or a fragment. A node always belongs to a Tree.
13
10
  #
14
- # All needed meta and processing information is associated with a Node. The meta information is
15
- # available throught the #[] and #meta_info accessors, the processing information through the
16
- # #node_info accessor.
11
+ # All needed meta and processing information is associated with the node itself. The meta
12
+ # information is available through the #[] and #meta_info accessors, the internal processing
13
+ # information through the #node_info accessor.
17
14
  #
18
- # Although node information should be changed by code, it is not advised to change meta
19
- # information values in code since this may lead to unwanted behaviour!
20
15
  class Node
21
16
 
22
- include WebsiteAccess
23
- include Loggable
24
-
25
17
  # The parent node. This is in all but one case a Node object. The one exception is that the
26
18
  # parent of the Tree#dummy_node is a Tree object.
27
19
  attr_reader :parent
@@ -29,21 +21,15 @@ module Webgen
29
21
  # The child nodes of this node.
30
22
  attr_reader :children
31
23
 
32
- # The full output path of this node.
33
- attr_reader :path
34
-
35
- # The tree to which this node belongs.
36
- attr_reader :tree
37
-
38
24
  # The canonical name of this node.
39
25
  attr_reader :cn
40
26
 
41
- # The absolute canonical name of this node.
42
- attr_reader :acn
43
-
44
27
  # The localized canonical name of this node.
45
28
  attr_reader :lcn
46
29
 
30
+ # The absolute canonical name of this node.
31
+ attr_reader :acn
32
+
47
33
  # The absolute localized canonical name of this node.
48
34
  attr_reader :alcn
49
35
 
@@ -53,51 +39,63 @@ module Webgen
53
39
  # The language of this node.
54
40
  attr_reader :lang
55
41
 
56
- # Meta information associated with the node.
42
+ # Meta information associated with the node. If you need just a value for a meta information
43
+ # key, use the #[] method.
57
44
  attr_reader :meta_info
58
45
 
46
+ # Return the node information hash which contains information for processing the node.
47
+ attr_reader :node_info
48
+
49
+ # The full destination path of this node.
50
+ attr_reader :dest_path
51
+
52
+ # The tree to which this node belongs.
53
+ attr_reader :tree
54
+
55
+
59
56
  # Create a new Node instance.
60
57
  #
61
58
  # [+parent+ (immutable)]
62
59
  # The parent node under which this nodes should be created.
63
- # [+path+ (immutable)]
64
- # The full output path for this node. If this node is a directory, the path must have a
65
- # trailing slash (<tt>dir/</tt>). If it is a fragment, the hash sign must be the first
66
- # character of the path (<tt>#fragment</tt>). This can also be an absolute path like
67
- # <tt>http://myhost.com/</tt>.
60
+ #
68
61
  # [+cn+ (immutable)]
69
- # The canonical name for this node. Needs to be of the form <tt>basename.ext</tt> or
70
- # <tt>basename</tt> where +basename+ does not contain any dots. Also, the +basename+ must not
71
- # include a language part!
62
+ # The canonical name for this node. Needs to be of the form 'basename.ext' or 'basename'
63
+ # where +basename+ does not contain any dots. Also, the +basename+ must not include a
64
+ # language part!
65
+ #
66
+ # [+dest_path+ (immutable)]
67
+ # The full output path for this node. If this node is a directory, the path must have a
68
+ # trailing slash ('dir/'). If it is a fragment, it has to include a hash sign. This can also
69
+ # be an absolute path like http://example.com.
70
+ #
72
71
  # [+meta_info+]
73
72
  # A hash with meta information for the new node.
74
73
  #
75
74
  # The language of a node is taken from the meta information +lang+ and the entry is deleted from
76
75
  # the meta information hash. The language cannot be changed afterwards! If no +lang+ key is
77
- # found, the node is language neutral.
78
- def initialize(parent, path, cn, meta_info = {})
76
+ # found, the node is unlocalized.
77
+ def initialize(parent, cn, dest_path, meta_info = {})
79
78
  @parent = parent
80
- @cn = cn.freeze
81
79
  @children = []
82
- reinit(path, meta_info)
83
- init_rest
84
- end
80
+ @cn = cn.freeze
81
+ @dest_path = dest_path.freeze
85
82
 
86
- # Re-initializes an already initialized node and resets it to its pristine state.
87
- def reinit(path, meta_info = {})
88
- old_path = @path if defined?(@path)
89
- @path = path.freeze
90
83
  @lang = Webgen::LanguageManager.language_for_code(meta_info.delete('lang'))
91
84
  @lang = nil unless is_file?
85
+
86
+ @lcn = Webgen::Path.lcn(@cn, @lang).freeze
87
+ @acn = (@parent.kind_of?(Webgen::Node) ? @parent.acn.sub(/#.*$/, '') + @cn : '').freeze
88
+ @alcn = (@parent.kind_of?(Webgen::Node) ? @parent.alcn.sub(/#.*$/, '') + @lcn : '').freeze
89
+
92
90
  @meta_info = meta_info
93
- @flags = Set.new([:dirty, :created])
94
- if defined?(@tree)
95
- @tree.node_access[:path].delete(old_path) if old_path
96
- @tree.register_path(self)
97
- self.node_info.clear
98
- self.node_info[:used_nodes] = Set.new
99
- self.node_info[:used_meta_info_nodes] = Set.new
100
- end
91
+ @node_info = {}
92
+
93
+ @level = -1
94
+ @tree = @parent
95
+ (@level += 1; @tree = @tree.parent) while @tree.kind_of?(Webgen::Node)
96
+
97
+ @tree.register_node(self)
98
+ @parent.children << self unless @parent == @tree
101
99
  end
102
100
 
103
101
  # Return the meta information item for +key+.
@@ -105,390 +103,147 @@ module Webgen
105
103
  @meta_info[key]
106
104
  end
107
105
 
108
- # Assign +value+ to the meta information item for +key+.
109
- def []=(key, value)
110
- @meta_info[key] = value
111
- end
112
-
113
- # Return the node information hash which contains information for processing the node.
114
- def node_info
115
- tree.node_info[@alcn] ||= {}
116
- end
117
-
118
106
  # Check if the node is a directory.
119
- def is_directory?; @path[-1] == ?/ && !is_fragment?; end
120
-
121
- # Check if the node is a file.
122
- def is_file?; !is_directory? && !is_fragment?; end
123
-
124
- # Check if the node is a fragment.
125
- def is_fragment?; @cn[0] == ?# end
126
-
127
- # Check if the node is the root node.
128
- def is_root?; self == tree.root; end
129
-
130
- # Check if the node is flagged with one of the following:
131
- #
132
- # [:created] Has the node been created or has it been read from the cache?
133
- # [:reinit] Does the node need to be reinitialized?
134
- # [:dirty] Set by other objects to +true+ if they think the object has changed since the last
135
- # run. Must not be set to +false+ once it is +true+!
136
- # [:dirty_meta_info] Set by other objects to +true+ if the meta information of the node has
137
- # changed since the last run. Must not be set to +false+ once it is +true+!
138
- def flagged?(key)
139
- @flags.include?(key)
107
+ def is_directory?
108
+ @cn[-1] == ?/ && !is_fragment?
140
109
  end
141
110
 
142
- # Flag the node with the +keys+ and dispatch the message <tt>:node_flagged</tt> with +self+ and
143
- # +keys+ as arguments. See #flagged for valid keys.
144
- def flag(*keys)
145
- @flags += keys
146
- website.blackboard.dispatch_msg(:node_flagged, self, keys)
147
- end
148
-
149
- # Remove the flags +keys+ from the node and dispatch the message <tt>:node_unflagged</tt> with
150
- # +self+ and +keys+ as arguments.
151
- def unflag(*keys)
152
- @flags.subtract(keys)
153
- website.blackboard.dispatch_msg(:node_unflagged, self, keys)
111
+ # Check if the node is a file.
112
+ def is_file?
113
+ !is_directory? && !is_fragment?
154
114
  end
155
115
 
156
- # Return +true+ if the node has changed since the last webgen run. If it has changed, +dirty+ is
157
- # set to +true+.
158
- #
159
- # Sends the message <tt>:node_changed?</tt> with +self+ as argument unless the node is already
160
- # dirty. A listener to this message should set the flag <tt>:dirty</tt> on the passed node if he
161
- # thinks it is dirty.
162
- def changed?
163
- if_not_checked(:node) do
164
- flag(:dirty) if meta_info_changed? || user_nodes_changed? ||
165
- node_info[:used_nodes].any? {|n| n != @alcn && (!tree[n] || tree[n].changed?)} ||
166
- node_info[:used_meta_info_nodes].any? {|n| n != @alcn && (!tree[n] || tree[n].meta_info_changed?)}
167
- website.blackboard.dispatch_msg(:node_changed?, self) unless flagged?(:dirty)
168
- end
169
- flagged?(:dirty)
116
+ # Check if the node is a fragment.
117
+ def is_fragment?
118
+ @cn[0] == ?#
170
119
  end
171
120
 
172
- # Return +true+ if any node matching a pattern from the meta information +used_nodes+ has changed.
173
- def user_nodes_changed?
174
- pattern = [@meta_info['used_nodes']].flatten.compact.collect {|pat| Webgen::Path.make_absolute(parent.alcn, pat)}
175
- tree.node_access[:alcn].any? do |path, n|
176
- pattern.any? {|pat| n =~ pat && n.changed?}
177
- end if pattern.length > 0
121
+ # Check if the node is the root node.
122
+ def is_root?
123
+ self == tree.root
178
124
  end
179
- private :user_nodes_changed?
180
125
 
181
- # Return +true+ if the meta information of the node has changed.
126
+ # Check if the this node is an ancestor of +node+.
182
127
  #
183
- # Sends the message <tt>:node_meta_info_changed?</tt> with +self+ as argument unless the meta
184
- # information of the node is already dirty. A listener to this message should set the flag
185
- # <tt>:dirt_meta_info</tt> on the passed node if he thinks that the node's meta information is
186
- # dirty.
187
- def meta_info_changed?
188
- if_not_checked(:meta_info) do
189
- website.blackboard.dispatch_msg(:node_meta_info_changed?, self) unless flagged?(:dirty_meta_info)
190
- end
191
- flagged?(:dirty_meta_info)
128
+ # The check is performed using only the +parent+ information of the involved nodes, NOT the
129
+ # actual alcn values!
130
+ def is_ancestor_of?(node)
131
+ node = node.parent
132
+ node = node.parent while node != tree.dummy_root && node != self
133
+ node != tree.dummy_root
192
134
  end
193
135
 
194
- # Return the string representation of the node which is just the alcn.
136
+ # Return the string representation of the node which is just the #alcn.
195
137
  def to_s
196
138
  @alcn
197
139
  end
198
140
 
199
- # Return an informative representation of the node.
200
- def inspect
141
+ def inspect #:nodoc:
201
142
  "<##{self.class.name}: alcn=#{@alcn}>"
202
143
  end
203
144
 
204
- # Return +true+ if the alcn matches the pattern. See Webgen::Path.match for more information.
145
+ # Return +true+ if the #alcn matches the pattern.
146
+ #
147
+ # See Webgen::Path.matches_pattern? for more information.
205
148
  def =~(pattern)
206
- Webgen::Path.match(@alcn, pattern)
207
- end
208
-
209
- # Sort nodes by using the meta info +sort_info+ (or +title+ if +sort_info+ is not set) of both
210
- # involved nodes.
211
- def <=>(other)
212
- self_so = (@meta_info['sort_info'] && @meta_info['sort_info'].to_s) || @meta_info['title'] || ''
213
- other_so = (other['sort_info'] && other['sort_info'].to_s) || other['title'] || ''
214
- if self_so !~ /\D/ && other_so !~ /\D/
215
- self_so = self_so.to_i
216
- other_so = other_so.to_i
217
- end
218
- self_so <=> other_so
219
- end
220
-
221
- # This pattern is the the same as URI::UNSAFE except that the hash character (#) is also
222
- # not escaped. This is needed sothat paths with fragments work correctly.
223
- URL_UNSAFE_PATTERN = Regexp.new("[^#{URI::PATTERN::UNRESERVED}#{URI::PATTERN::RESERVED}#]") # :nodoc:
224
-
225
- # Construct an internal URL for the given +name+ which can be an acn/alcn/path. If the parameter
226
- # +make_absolute+ is +true+, then a relative URL will be made absolute by prepending the special
227
- # URL <tt>webgen:://webgen.localhost/</tt>.
228
- def self.url(name, make_absolute = true)
229
- url = URI::parse(URI::escape(name, URL_UNSAFE_PATTERN))
230
- url = URI::parse('webgen://webgen.localhost/') + url unless url.absolute? || !make_absolute
231
- url
149
+ Webgen::Path.matches_pattern?(@alcn, pattern)
232
150
  end
233
151
 
234
-
235
- # Check if the this node is in the subtree which is spanned by +node+. The check is performed
236
- # using only the +parent+ information of the involved nodes, NOT the actual path/alcn values!
237
- def in_subtree_of?(node)
238
- temp = self
239
- temp = temp.parent while temp != tree.dummy_root && temp != node
240
- temp != tree.dummy_root
241
- end
242
-
243
- # Return the node with the same canonical name but in language +lang+ or, if no such node
244
- # exists, an unlocalized version of the node. If no such node is found either, +nil+ is
245
- # returned.
246
- def in_lang(lang)
247
- avail = @tree.node_access[:acn][@acn]
248
- avail.find do |n|
249
- n = n.parent while n.is_fragment?
250
- n.lang == lang
251
- end || avail.find do |n|
252
- n = n.parent while n.is_fragment?
253
- n.lang.nil?
254
- end
255
- end
256
-
257
- # Return the node representing the given +path+ which can be an acn/alcn. The path can be
258
- # absolute (i.e. starting with a slash) or relative to the current node. If no node exists for
259
- # the given path or if the path is invalid, +nil+ is returned.
152
+ # Return the node representing the given +path+ in the given language.
260
153
  #
261
- # If the +path+ is an alcn and a node is found, it is returned. If the +path+ is an acn, the
262
- # correct localized node according to +lang+ is returned or if no such node exists but an
263
- # unlocalized version does, the unlocalized node is returned.
264
- def resolve(path, lang = nil, use_passive_sources = true)
265
- orig_path = path
266
- url = self.class.url(@alcn) + self.class.url(path, false)
267
-
268
- path = url.path + (url.fragment.nil? ? '' : '#' + url.fragment)
269
- return nil if path =~ /^\/\.\./
270
-
271
- node = @tree[path, :alcn]
272
- if !node || node.acn == path
273
- (node = (@tree[path, :acn] || @tree[path + '/', :acn])) && (node = node.in_lang(lang))
274
- end
275
- if !node && use_passive_sources && !website.config['passive_sources'].empty?
276
- nodes = website.blackboard.invoke(:create_nodes_from_paths, [path])
277
- node = resolve(orig_path, lang, false)
278
- node.node_info[:used_meta_info_nodes] += nodes.collect {|n| n.alcn} if node
279
- end
280
- node
154
+ # The path can be absolute (i.e. starting with a slash) or relative to the current node.
155
+ # Relative paths are made absolute by using the #alcn of the current node.
156
+ #
157
+ # If the +lang+ parameter is not used, it defaults to the language of the current node.
158
+ #
159
+ # See Tree#resolve_node for detailed information on how the correct node for the path is found
160
+ # and for the +msg_on_failure+ parameter.
161
+ def resolve(path, lang = @lang, msg_on_failure = false)
162
+ @tree.resolve_node(Webgen::Path.append(@alcn, path), lang, msg_on_failure)
281
163
  end
282
164
 
283
- # Return the relative path to the given path +other+. The parameter +other+ can be a Node or a
284
- # String.
285
- def route_to(other)
286
- my_url = self.class.url(@path)
287
- other_url = if other.kind_of?(Node)
288
- self.class.url(other.routing_node(@lang).path)
289
- elsif other.kind_of?(String)
290
- my_url + other
291
- else
292
- raise ArgumentError, "improper class for argument"
293
- end
165
+ # Return the relative path to the given node.
166
+ #
167
+ # If the +lang+ parameter is not used, it defaults to the language of the current node.
168
+ def route_to(node, lang = @lang)
169
+ my_url = Webgen::Path.url(@dest_path)
170
+ other_url = Webgen::Path.url(node.proxy_node(lang).dest_path)
294
171
 
295
172
  # resolve any '.' and '..' paths in the target url
296
173
  if other_url.path =~ /\/\.\.?\// && other_url.scheme == 'webgen'
297
174
  other_url.path = Pathname.new(other_url.path).cleanpath.to_s
298
175
  end
299
176
  route = my_url.route_to(other_url).to_s
300
- (route == '' ? File.basename(self.path) : route)
177
+ (route == '' ? File.basename(@dest_path) : route)
301
178
  end
302
179
 
303
- # Return the routing node in language +lang+ which is the node that is used when routing to this
304
- # node. The returned node can differ from the node itself in case of a directory where the
305
- # routing node is the directory index node. If +show_warning+ is +true+ and this node is a
306
- # directory node, then a warning is logged if no associated index file is found.
307
- def routing_node(lang, log_warning = true)
308
- if !is_directory?
180
+ # Return the proxy node in language +lang+.
181
+ #
182
+ # This node should be used, for example, when routing to this node. The proxy node is found by
183
+ # using the +proxy_path+ meta information. This meta information is usually set on directories
184
+ # to specify the node that should be used for the "directory index".
185
+ #
186
+ # If the +lang+ parameter is not used, it defaults to the language of the current node.
187
+ def proxy_node(lang = @lang)
188
+ proxy_path = self['proxy_path']
189
+ if proxy_path.nil?
309
190
  self
310
191
  else
311
- key = [alcn, :index_node, lang]
312
- vcache = website.cache.volatile
313
- return vcache[key] if vcache.has_key?(key)
314
-
315
- index_path = self.meta_info['index_path']
316
- if index_path.nil?
317
- vcache[key] = self
318
- else
319
- index_node = resolve(index_path, lang)
320
- if index_node
321
- vcache[key] = index_node
322
- log(:info) { "Directory index path for <#{alcn}> => <#{index_node}>" }
323
- elsif log_warning
324
- vcache[key] = self
325
- log(:warn) { "No directory index path found for directory <#{alcn}>" }
326
- end
327
- end
328
- vcache[key] || self
192
+ resolve(proxy_path, lang, true) || self
329
193
  end
330
194
  end
331
195
 
332
- # Return a HTML link from this node to the +node+ or, if this node and +node+ are the same and
333
- # the parameter <tt>website.link_to_current_page</tt> is +false+, a +span+ element with the link
334
- # text.
196
+ # Return a HTML link from this node to the given node.
197
+ #
198
+ # If the +lang+ parameter is not used, it defaults to the language of the current node.
335
199
  #
336
200
  # You can optionally specify additional attributes for the HTML element in the +attr+ Hash.
337
201
  # Also, the meta information +link_attrs+ of the given +node+ is used, if available, to set
338
202
  # attributes. However, the +attr+ parameter takes precedence over the +link_attrs+ meta
339
203
  # information. Be aware that all key-value pairs with Symbol keys are removed before the
340
- # attributes are written. Therefore you always need to specify general attributes with Strings!
341
- #
342
- # If the special value <tt>:link_text</tt> is present in the attributes, it will be used as the
343
- # link text; otherwise the title of the +node+ will be used.
204
+ # attributes are written. Therefore you always need to specify general attributes with strings!
344
205
  #
345
- # If the special value <tt>:lang</tt> is present in the attributes, it will be used as parameter
346
- # to the <tt>node.routing_node</tt> call for getting the linked-to node instead of this node's
347
- # +lang+ attribute. *Note*: this is only useful when linking to a directory.
348
- def link_to(node, attr = {})
206
+ # If the special value :link_text is present in the attributes, it will be used as the link
207
+ # text; otherwise the title of the +node+ will be used.
208
+ def link_to(node, lang = @lang, attr = {})
349
209
  attr = node['link_attrs'].merge(attr) if node['link_attrs'].kind_of?(Hash)
350
- rnode = node.routing_node(attr[:lang] || @lang)
210
+ rnode = node.proxy_node(lang)
351
211
  link_text = attr[:link_text] || (rnode != node && rnode['routed_title']) || node['title']
352
212
  attr.delete_if {|k,v| k.kind_of?(Symbol)}
353
213
 
354
- use_link = (rnode != self || website.config['website.link_to_current_page'])
355
- attr['href'] = self.route_to(rnode) if use_link
214
+ attr['href'] = self.route_to(node, lang)
215
+ attr['hreflang'] = rnode.lang.to_s if rnode.lang
356
216
  attrs = attr.collect {|name,value| "#{name.to_s}=\"#{value}\"" }.sort.unshift('').join(' ')
357
- (use_link ? "<a#{attrs}>#{link_text}</a>" : "<span#{attrs}>#{link_text}</span>")
217
+ "<a#{attrs}>#{link_text}</a>"
358
218
  end
359
219
 
360
- def find(opts = {})
361
- if opts[:alcn]
362
- opts[:alcn] = Path.make_absolute(is_directory? ? alcn : parent.alcn.sub(/#.*$/, ''), opts[:alcn].to_s)
363
- end
364
- opts[:levels] = 100000 unless opts.has_key?(:levels)
365
-
366
- result = find_nodes(opts, nil, 1)
367
- result.flatten! if result && (opts[:limit] || opts[:offset])
368
- result.sort!(opts[:sort]) if result
369
- result.children = result.children[(opts[:offset].to_s.to_i)..(opts[:limit] ? opts[:offset].to_s.to_i + opts[:limit].to_s.to_i - 1 : -1)]
370
- result
220
+ # Return all versions of this node.
221
+ def versions
222
+ tree.node_access[:alcn].select {|alcn, n| n.node_info[:path] == node_info[:path]}.
223
+ each_with_object({}) {|(k, v), h| h[v['version']] = v}
371
224
  end
372
225
 
373
- def find_nodes(opts, parent, level)
374
- result = ProxyNode.new(parent, self)
375
-
376
- children.each do |child|
377
- c_result = child.find_nodes(opts, result, level + 1)
378
- result.children << c_result unless c_result.nil?
379
- end if opts[:levels] && level <= opts[:levels]
380
-
381
- (!result.children.empty? || find_match?(opts) ? result : nil)
382
- end
383
- protected :find_nodes
384
-
385
- def find_match?(opts)
386
- (!opts[:alcn] || self =~ opts[:alcn])
387
- end
388
- private :find_match?
389
226
 
390
227
  #######
391
228
  private
392
229
  #######
393
230
 
394
- # Do the rest of the initialization.
395
- def init_rest
396
- @lcn = Path.lcn(@cn, @lang)
397
- @acn = (@parent.kind_of?(Tree) ? '' : @parent.acn.sub(/#.*$/, '') + @cn)
398
- @alcn = (@parent.kind_of?(Tree) ? '' : @parent.alcn.sub(/#.*$/, '') + @lcn)
399
-
400
- @level = -1
401
- @tree = @parent
402
- (@level += 1; @tree = @tree.parent) while !@tree.kind_of?(Tree)
403
-
404
- @tree.register_node(self)
405
- @parent.children << self unless @parent == @tree
406
-
407
- self.node_info[:used_nodes] = Set.new
408
- self.node_info[:used_meta_info_nodes] = Set.new
409
- end
410
-
411
- # Only run the code in the block if this node has not already been checked. Different checks are
412
- # supported by setting a different +type+ value.
413
- def if_not_checked(type)
414
- array = (website.cache.volatile[:node_change_checking] ||= {})[type] ||= []
415
- if !array.include?(self)
416
- array << self
417
- yield
418
- array.delete(self)
419
- end
420
- end
421
-
422
- # Delegate missing methods to a processor. The current node is placed into the argument array as
423
- # the first argument before the method +name+ is invoked on the processor.
231
+ # Delegate missing methods to the associated path handler. The current node is placed into the
232
+ # argument array as the first argument before the method +name+ is invoked on the path handler.
424
233
  def method_missing(name, *args, &block)
425
- if node_info[:processor]
426
- website.cache.instance(node_info[:processor]).send(name, *([self] + args), &block)
234
+ if node_info[:path_handler]
235
+ node_info[:path_handler].send(name, *([self] + args), &block)
427
236
  else
428
237
  super
429
238
  end
430
239
  end
431
240
 
432
- end
433
-
434
- # Encapsulates a node. This class is needed when a hierarchy of nodes should be created but the
435
- # original hierarchy should not be destroyed.
436
- class ProxyNode
437
-
438
- # Array of child proxy nodes.
439
- attr_accessor :children
440
-
441
- # The parent proxy node.
442
- attr_accessor :parent
443
-
444
- # The encapsulated node.
445
- attr_reader :node
446
-
447
- # Create a new proxy node under +parent+ (also has to be a ProxyNode object) for the real node
448
- # +node+.
449
- def initialize(parent, node)
450
- @parent = parent
451
- @node = node
452
- @children = []
453
- end
454
-
455
- # Sort recursively all children of the node using the wrapped nodes. If +value+ is +false+, no
456
- # sorting is done at all. If it is +true+, then the default sort mechanism is used (see
457
- # Node#<=>). Otherwise +value+ has to be a meta information key on which should be sorted.
458
- def sort!(value = true)
459
- return self unless value
460
-
461
- if value.kind_of?(String)
462
- self.children.sort! do |a,b|
463
- aval, bval = a.node[value].to_s, b.node[value].to_s
464
- if aval !~ /\D/ && aval !~ /\D/
465
- aval = aval.to_i
466
- bval = bval.to_i
467
- end
468
- aval <=> bval
469
- end
241
+ def respond_to_missing?(symbol, include_private) #:nodoc:
242
+ if node_info[:path_handler]
243
+ node_info[:path_handler].send(:respond_to?, symbol, include_private)
470
244
  else
471
- self.children.sort! {|a,b| a.node <=> b.node}
472
- end
473
- self.children.each {|child| child.sort!(value)}
474
- self
475
- end
476
-
477
- # Turn the hierarchy of proxy nodes into a flat list.
478
- def flatten!
479
- result = []
480
- while !self.children.empty?
481
- result << self.children.shift
482
- result.last.parent = self
483
- self.children.unshift(*result.last.children)
484
- result.last.children = []
245
+ super
485
246
  end
486
- self.children = result
487
- end
488
-
489
- # Return the hierarchy under this node as nested list of alcn values.
490
- def to_list
491
- self.children.inject([]) {|temp, n| temp << n.node.alcn; temp += ((t = n.to_list).empty? ? [] : [t]) }
492
247
  end
493
248
 
494
249
  end