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,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