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.
- data/API.rdoc +143 -0
- data/AUTHORS +0 -1
- data/COPYING +17 -8
- data/ChangeLog +4456 -0
- data/GPL +623 -289
- data/README.md +71 -0
- data/Rakefile +87 -99
- data/VERSION +1 -1
- data/bin/webgen +1 -7
- data/data/webgen/basic_website_template/ext/init.rb +15 -0
- data/data/webgen/basic_website_template/webgen.config +18 -0
- data/data/webgen/bundle_template_files/README.md.erb +24 -0
- data/data/webgen/bundle_template_files/Rakefile.erb +36 -0
- data/data/webgen/bundle_template_files/info.yaml.erb +16 -0
- data/data/webgen/bundle_template_files/init.rb.erb +1 -0
- data/data/webgen/passive_sources/default.metainfo +32 -0
- data/data/webgen/passive_sources/stylesheets/coderay-default.css +109 -118
- data/data/webgen/passive_sources/templates/feed.template +62 -0
- data/data/webgen/passive_sources/templates/sitemap.template +3 -6
- data/data/webgen/passive_sources/templates/tag.template +42 -0
- data/data/webgen/website_bundles/default/README +2 -2
- data/lib/webgen/blackboard.rb +15 -51
- data/lib/webgen/bundle/built-in-show-changes/init.rb +54 -0
- data/lib/webgen/bundle/built-in/init.rb +366 -0
- data/lib/webgen/bundle_loader.rb +126 -0
- data/lib/webgen/cache.rb +9 -18
- data/lib/webgen/cli.rb +131 -58
- data/lib/webgen/cli/bundle_command.rb +30 -0
- data/lib/webgen/cli/create_bundle_command.rb +46 -0
- data/lib/webgen/cli/create_command.rb +48 -60
- data/lib/webgen/cli/generate_command.rb +25 -0
- data/lib/webgen/cli/install_bundle_command.rb +34 -0
- data/lib/webgen/cli/list_bundle_command.rb +108 -0
- data/lib/webgen/cli/logger.rb +45 -0
- data/lib/webgen/cli/show_command.rb +30 -0
- data/lib/webgen/cli/show_config_command.rb +63 -0
- data/lib/webgen/cli/show_dependencies_command.rb +103 -0
- data/lib/webgen/cli/show_extensions_command.rb +74 -0
- data/lib/webgen/cli/utils.rb +68 -95
- data/lib/webgen/configuration.rb +143 -105
- data/lib/webgen/content_processor.rb +160 -0
- data/lib/webgen/content_processor/blocks.rb +96 -0
- data/lib/webgen/content_processor/builder.rb +25 -0
- data/lib/webgen/content_processor/erb.rb +25 -0
- data/lib/webgen/content_processor/erubis.rb +31 -0
- data/lib/webgen/content_processor/fragments.rb +82 -0
- data/lib/webgen/content_processor/haml.rb +25 -0
- data/lib/webgen/content_processor/html_head.rb +157 -0
- data/lib/webgen/content_processor/kramdown.rb +49 -0
- data/lib/webgen/content_processor/maruku.rb +39 -0
- data/lib/webgen/content_processor/r_discount.rb +21 -0
- data/lib/webgen/content_processor/rdoc.rb +22 -0
- data/lib/webgen/content_processor/redcloth.rb +23 -0
- data/lib/webgen/content_processor/ruby.rb +20 -0
- data/lib/webgen/content_processor/sass.rb +145 -0
- data/lib/webgen/content_processor/scss.rb +23 -0
- data/lib/webgen/content_processor/tags.rb +30 -0
- data/lib/webgen/content_processor/tidy.rb +32 -0
- data/lib/webgen/content_processor/tikz.rb +116 -0
- data/lib/webgen/content_processor/xmllint.rb +31 -0
- data/lib/webgen/context.rb +57 -29
- data/lib/webgen/context/html_head.rb +60 -0
- data/lib/webgen/context/nodes.rb +32 -27
- data/lib/webgen/context/rendering.rb +39 -0
- data/lib/webgen/context/webgen_tags.rb +25 -0
- data/lib/webgen/core_ext.rb +25 -0
- data/lib/webgen/destination.rb +151 -0
- data/lib/webgen/destination/file_system.rb +62 -0
- data/lib/webgen/error.rb +59 -49
- data/lib/webgen/extension_manager.rb +121 -0
- data/lib/webgen/item_tracker.rb +237 -0
- data/lib/webgen/item_tracker/file.rb +39 -0
- data/lib/webgen/item_tracker/missing_node.rb +61 -0
- data/lib/webgen/item_tracker/node_content.rb +40 -0
- data/lib/webgen/item_tracker/node_meta_info.rb +53 -0
- data/lib/webgen/item_tracker/nodes.rb +92 -0
- data/lib/webgen/logger.rb +26 -82
- data/lib/webgen/node.rb +122 -367
- data/lib/webgen/node_finder.rb +336 -0
- data/lib/webgen/page.rb +48 -85
- data/lib/webgen/path.rb +218 -156
- data/lib/webgen/path_handler.rb +400 -0
- data/lib/webgen/path_handler/base.rb +220 -0
- data/lib/webgen/path_handler/copy.rb +78 -0
- data/lib/webgen/path_handler/directory.rb +21 -0
- data/lib/webgen/path_handler/feed.rb +82 -0
- data/lib/webgen/path_handler/meta_info.rb +84 -0
- data/lib/webgen/path_handler/page.rb +38 -0
- data/lib/webgen/path_handler/page_utils.rb +79 -0
- data/lib/webgen/path_handler/sitemap.rb +52 -0
- data/lib/webgen/path_handler/template.rb +96 -0
- data/lib/webgen/path_handler/virtual.rb +85 -0
- data/lib/webgen/{webgentask.rb → rake_task.rb} +31 -27
- data/lib/webgen/source.rb +106 -24
- data/lib/webgen/source/file_system.rb +41 -0
- data/lib/webgen/source/stacked.rb +49 -53
- data/lib/webgen/source/tar_archive.rb +59 -0
- data/lib/webgen/tag.rb +250 -19
- data/lib/webgen/tag/breadcrumb_trail.rb +65 -0
- data/lib/webgen/tag/coderay.rb +32 -35
- data/lib/webgen/tag/date.rb +9 -9
- data/lib/webgen/tag/execute_command.rb +31 -0
- data/lib/webgen/tag/include_file.rb +32 -0
- data/lib/webgen/tag/langbar.rb +31 -47
- data/lib/webgen/tag/link.rb +17 -18
- data/lib/webgen/tag/menu.rb +27 -189
- data/lib/webgen/tag/meta_info.rb +31 -0
- data/lib/webgen/tag/relocatable.rb +48 -39
- data/lib/webgen/tag/tikz.rb +24 -100
- data/lib/webgen/task.rb +99 -0
- data/lib/webgen/task/create_bundle.rb +73 -0
- data/lib/webgen/task/create_website.rb +94 -0
- data/lib/webgen/task/generate_website.rb +47 -0
- data/lib/webgen/test_helper.rb +183 -0
- data/lib/webgen/tree.rb +95 -46
- data/lib/webgen/utils.rb +39 -0
- data/lib/webgen/utils/external_command.rb +27 -0
- data/lib/webgen/utils/tag_parser.rb +124 -0
- data/lib/webgen/version.rb +1 -1
- data/lib/webgen/website.rb +134 -296
- data/setup.rb +1 -1
- data/test/test_documentation.rb +43 -0
- data/test/webgen/cli/test_logger.rb +41 -0
- data/test/{test_contentprocessor_blocks.rb → webgen/content_processor/test_blocks.rb} +30 -28
- data/test/webgen/content_processor/test_builder.rb +25 -0
- data/test/webgen/content_processor/test_erb.rb +21 -0
- data/test/webgen/content_processor/test_erubis.rb +33 -0
- data/test/webgen/content_processor/test_fragments.rb +96 -0
- data/test/webgen/content_processor/test_haml.rb +24 -0
- data/test/webgen/content_processor/test_html_head.rb +78 -0
- data/test/webgen/content_processor/test_kramdown.rb +49 -0
- data/test/webgen/content_processor/test_maruku.rb +30 -0
- data/test/webgen/content_processor/test_r_discount.rb +18 -0
- data/test/webgen/content_processor/test_rdoc.rb +18 -0
- data/test/webgen/content_processor/test_redcloth.rb +23 -0
- data/test/webgen/content_processor/test_ruby.rb +24 -0
- data/test/webgen/content_processor/test_sass.rb +44 -0
- data/test/webgen/content_processor/test_scss.rb +23 -0
- data/test/webgen/content_processor/test_tags.rb +44 -0
- data/test/webgen/content_processor/test_tidy.rb +31 -0
- data/test/webgen/content_processor/test_tikz.rb +33 -0
- data/test/webgen/content_processor/test_xmllint.rb +32 -0
- data/test/webgen/destination/test_file_system.rb +54 -0
- data/test/webgen/item_tracker/test_file.rb +31 -0
- data/test/webgen/item_tracker/test_missing_node.rb +70 -0
- data/test/webgen/item_tracker/test_node_content.rb +42 -0
- data/test/webgen/item_tracker/test_node_meta_info.rb +44 -0
- data/test/webgen/item_tracker/test_nodes.rb +61 -0
- data/test/webgen/path_handler/test_base.rb +153 -0
- data/test/webgen/path_handler/test_copy.rb +56 -0
- data/test/webgen/path_handler/test_feed.rb +85 -0
- data/test/webgen/path_handler/test_meta_info.rb +98 -0
- data/test/webgen/path_handler/test_page.rb +25 -0
- data/test/webgen/path_handler/test_page_utils.rb +59 -0
- data/test/webgen/path_handler/test_sitemap.rb +95 -0
- data/test/webgen/path_handler/test_template.rb +64 -0
- data/test/webgen/path_handler/test_virtual.rb +87 -0
- data/test/webgen/source/test_file_system.rb +51 -0
- data/test/webgen/source/test_stacked.rb +35 -0
- data/test/{test_source_tararchive.rb → webgen/source/test_tar_archive.rb} +10 -25
- data/test/webgen/tag/test_breadcrumb_trail.rb +66 -0
- data/test/webgen/tag/test_coderay.rb +34 -0
- data/test/webgen/tag/test_date.rb +18 -0
- data/test/webgen/tag/test_execute_command.rb +36 -0
- data/test/webgen/tag/test_include_file.rb +35 -0
- data/test/webgen/tag/test_langbar.rb +50 -0
- data/test/webgen/tag/test_link.rb +40 -0
- data/test/webgen/tag/test_menu.rb +61 -0
- data/test/webgen/tag/test_meta_info.rb +25 -0
- data/test/webgen/tag/test_relocatable.rb +50 -0
- data/test/webgen/tag/test_tikz.rb +41 -0
- data/test/webgen/task/test_create_website.rb +46 -0
- data/test/webgen/test_blackboard.rb +31 -0
- data/test/webgen/test_bundle_loader.rb +55 -0
- data/test/{test_cache.rb → webgen/test_cache.rb} +3 -15
- data/test/webgen/test_cli.rb +41 -0
- data/test/webgen/test_configuration.rb +131 -0
- data/test/webgen/test_content_processor.rb +86 -0
- data/test/webgen/test_context.rb +73 -0
- data/test/webgen/test_core_ext.rb +20 -0
- data/test/webgen/test_destination.rb +48 -0
- data/test/webgen/test_error.rb +121 -0
- data/test/webgen/test_extension_manager.rb +70 -0
- data/test/webgen/test_item_tracker.rb +106 -0
- data/test/{test_languages.rb → webgen/test_languages.rb} +4 -4
- data/test/webgen/test_logger.rb +46 -0
- data/test/webgen/test_node.rb +178 -0
- data/test/webgen/test_node_finder.rb +127 -0
- data/test/{test_page.rb → webgen/test_page.rb} +44 -48
- data/test/webgen/test_path.rb +271 -0
- data/test/{test_webgentask.rb → webgen/test_rake_task.rb} +4 -4
- data/test/webgen/test_source.rb +59 -0
- data/test/webgen/test_tag.rb +137 -0
- data/test/webgen/test_task.rb +40 -0
- data/test/webgen/test_tree.rb +147 -0
- data/test/webgen/test_utils.rb +16 -0
- data/test/webgen/test_website.rb +45 -0
- data/test/webgen/utils/test_tag_parser.rb +99 -0
- metadata +292 -344
- data/data/webgen/passive_sources/templates/atom_feed.template +0 -39
- data/data/webgen/passive_sources/templates/rss_feed.template +0 -28
- data/data/webgen/resources.yaml +0 -4
- data/data/webgen/webgui/app.rb +0 -11
- data/data/webgen/webgui/controller/main.rb +0 -135
- data/data/webgen/webgui/layout/default.xhtml +0 -40
- data/data/webgen/webgui/overrides/win32console.rb +0 -0
- data/data/webgen/webgui/public/css/jquery.autocomplete.css +0 -50
- data/data/webgen/webgui/public/css/ramaze_error.css +0 -90
- data/data/webgen/webgui/public/css/style.css +0 -55
- data/data/webgen/webgui/public/img/headerbg.jpg +0 -0
- data/data/webgen/webgui/public/img/webgen_logo.png +0 -0
- data/data/webgen/webgui/public/js/jquery.autocomplete.js +0 -15
- data/data/webgen/webgui/public/js/jquery.js +0 -32
- data/data/webgen/webgui/start.rb +0 -9
- data/data/webgen/webgui/view/create_website.xhtml +0 -14
- data/data/webgen/webgui/view/error.xhtml +0 -64
- data/data/webgen/webgui/view/index.xhtml +0 -22
- data/data/webgen/webgui/view/manage_website.xhtml +0 -18
- data/data/webgen/website_skeleton/README +0 -10
- data/data/webgen/website_skeleton/Rakefile +0 -69
- data/data/webgen/website_skeleton/config.yaml +0 -35
- data/data/webgen/website_skeleton/ext/init.rb +0 -10
- data/doc/contentprocessor.template +0 -11
- data/doc/contentprocessor/blocks.page +0 -129
- data/doc/contentprocessor/builder.page +0 -79
- data/doc/contentprocessor/erb.page +0 -60
- data/doc/contentprocessor/erubis.page +0 -46
- data/doc/contentprocessor/fragments.page +0 -26
- data/doc/contentprocessor/haml.page +0 -46
- data/doc/contentprocessor/head.page +0 -31
- data/doc/contentprocessor/kramdown.page +0 -49
- data/doc/contentprocessor/less.page +0 -34
- data/doc/contentprocessor/maruku.page +0 -44
- data/doc/contentprocessor/rdiscount.page +0 -37
- data/doc/contentprocessor/rdoc.page +0 -36
- data/doc/contentprocessor/redcloth.page +0 -41
- data/doc/contentprocessor/sass.page +0 -31
- data/doc/contentprocessor/scss.page +0 -39
- data/doc/contentprocessor/tags.page +0 -73
- data/doc/contentprocessor/tidy.page +0 -14
- data/doc/contentprocessor/xmllint.page +0 -14
- data/doc/extensions.metainfo +0 -29
- data/doc/extensions.page +0 -15
- data/doc/extensions.template +0 -17
- data/doc/faq.page +0 -222
- data/doc/getting_started.page +0 -135
- data/doc/index.page +0 -71
- data/doc/manual.page +0 -727
- data/doc/reference_configuration.page +0 -1254
- data/doc/reference_metainfo.page +0 -265
- data/doc/reference_website_styles.page +0 -32
- data/doc/source/filesystem.page +0 -41
- data/doc/source/tararchive.page +0 -40
- data/doc/sourcehandler.template +0 -23
- data/doc/sourcehandler/copy.page +0 -19
- data/doc/sourcehandler/directory.page +0 -27
- data/doc/sourcehandler/feed.page +0 -102
- data/doc/sourcehandler/metainfo.page +0 -48
- data/doc/sourcehandler/page.page +0 -14
- data/doc/sourcehandler/sitemap.page +0 -46
- data/doc/sourcehandler/template.page +0 -45
- data/doc/sourcehandler/virtual.page +0 -49
- data/doc/tag.template +0 -25
- data/doc/tag/breadcrumbtrail.page +0 -40
- data/doc/tag/coderay.page +0 -53
- data/doc/tag/date.page +0 -31
- data/doc/tag/executecommand.page +0 -26
- data/doc/tag/includefile.page +0 -32
- data/doc/tag/langbar.page +0 -47
- data/doc/tag/link.page +0 -44
- data/doc/tag/menu.page +0 -109
- data/doc/tag/metainfo.page +0 -29
- data/doc/tag/relocatable.page +0 -38
- data/doc/tag/sitemap.page +0 -31
- data/doc/tag/tikz.page +0 -159
- data/doc/upgrading.page +0 -138
- data/doc/webgen_page_format.page +0 -129
- data/doc/website_styles.metainfo +0 -8
- data/lib/webgen/cli/apply_command.rb +0 -66
- data/lib/webgen/cli/run_command.rb +0 -22
- data/lib/webgen/cli/webgui_command.rb +0 -68
- data/lib/webgen/common.rb +0 -27
- data/lib/webgen/common/sitemap.rb +0 -83
- data/lib/webgen/contentprocessor.rb +0 -117
- data/lib/webgen/contentprocessor/blocks.rb +0 -92
- data/lib/webgen/contentprocessor/builder.rb +0 -29
- data/lib/webgen/contentprocessor/erb.rb +0 -26
- data/lib/webgen/contentprocessor/erubis.rb +0 -39
- data/lib/webgen/contentprocessor/fragments.rb +0 -25
- data/lib/webgen/contentprocessor/haml.rb +0 -34
- data/lib/webgen/contentprocessor/head.rb +0 -128
- data/lib/webgen/contentprocessor/kramdown.rb +0 -27
- data/lib/webgen/contentprocessor/kramdown/html.rb +0 -36
- data/lib/webgen/contentprocessor/less.rb +0 -35
- data/lib/webgen/contentprocessor/maruku.rb +0 -36
- data/lib/webgen/contentprocessor/rdiscount.rb +0 -19
- data/lib/webgen/contentprocessor/rdoc.rb +0 -20
- data/lib/webgen/contentprocessor/redcloth.rb +0 -21
- data/lib/webgen/contentprocessor/sass.rb +0 -22
- data/lib/webgen/contentprocessor/scss.rb +0 -22
- data/lib/webgen/contentprocessor/tags.rb +0 -170
- data/lib/webgen/contentprocessor/tidy.rb +0 -38
- data/lib/webgen/contentprocessor/xmllint.rb +0 -37
- data/lib/webgen/context/render.rb +0 -32
- data/lib/webgen/context/tags.rb +0 -20
- data/lib/webgen/coreext.rb +0 -13
- data/lib/webgen/default_config.rb +0 -240
- data/lib/webgen/loggable.rb +0 -25
- data/lib/webgen/output.rb +0 -86
- data/lib/webgen/output/filesystem.rb +0 -69
- data/lib/webgen/source/filesystem.rb +0 -61
- data/lib/webgen/source/resource.rb +0 -45
- data/lib/webgen/source/tararchive.rb +0 -78
- data/lib/webgen/sourcehandler.rb +0 -275
- data/lib/webgen/sourcehandler/base.rb +0 -281
- data/lib/webgen/sourcehandler/copy.rb +0 -44
- data/lib/webgen/sourcehandler/directory.rb +0 -30
- data/lib/webgen/sourcehandler/feed.rb +0 -92
- data/lib/webgen/sourcehandler/fragment.rb +0 -70
- data/lib/webgen/sourcehandler/memory.rb +0 -42
- data/lib/webgen/sourcehandler/metainfo.rb +0 -128
- data/lib/webgen/sourcehandler/page.rb +0 -64
- data/lib/webgen/sourcehandler/sitemap.rb +0 -60
- data/lib/webgen/sourcehandler/template.rb +0 -66
- data/lib/webgen/sourcehandler/virtual.rb +0 -117
- data/lib/webgen/tag/base.rb +0 -170
- data/lib/webgen/tag/breadcrumbtrail.rb +0 -70
- data/lib/webgen/tag/executecommand.rb +0 -31
- data/lib/webgen/tag/includefile.rb +0 -42
- data/lib/webgen/tag/metainfo.rb +0 -27
- data/lib/webgen/tag/sitemap.rb +0 -41
- data/lib/webgen/websiteaccess.rb +0 -31
- data/lib/webgen/websitemanager.rb +0 -125
- data/misc/default.css +0 -403
- data/misc/default.template +0 -76
- data/misc/htmldoc.metainfo +0 -26
- data/misc/htmldoc.virtual +0 -17
- data/misc/images/arrow.gif +0 -0
- data/misc/images/error.png +0 -0
- data/misc/images/headerbg.jpg +0 -0
- data/misc/images/important.png +0 -0
- data/misc/images/information.png +0 -0
- data/misc/images/quote.gif +0 -0
- data/misc/images/warning.png +0 -0
- data/misc/logo.svg +0 -313
- data/misc/style.page +0 -33
- data/test/helper.rb +0 -61
- data/test/test_blackboard.rb +0 -60
- data/test/test_cli.rb +0 -119
- data/test/test_common_sitemap.rb +0 -58
- data/test/test_configuration.rb +0 -68
- data/test/test_contentprocessor.rb +0 -39
- data/test/test_contentprocessor_builder.rb +0 -41
- data/test/test_contentprocessor_erb.rb +0 -33
- data/test/test_contentprocessor_erubis.rb +0 -62
- data/test/test_contentprocessor_fragments.rb +0 -43
- data/test/test_contentprocessor_haml.rb +0 -39
- data/test/test_contentprocessor_head.rb +0 -96
- data/test/test_contentprocessor_kramdown.rb +0 -56
- data/test/test_contentprocessor_less.rb +0 -40
- data/test/test_contentprocessor_maruku.rb +0 -33
- data/test/test_contentprocessor_rdiscount.rb +0 -21
- data/test/test_contentprocessor_rdoc.rb +0 -22
- data/test/test_contentprocessor_redcloth.rb +0 -26
- data/test/test_contentprocessor_sass.rb +0 -28
- data/test/test_contentprocessor_scss.rb +0 -28
- data/test/test_contentprocessor_tags.rb +0 -122
- data/test/test_contentprocessor_tidy.rb +0 -34
- data/test/test_contentprocessor_xmllint.rb +0 -38
- data/test/test_context.rb +0 -81
- data/test/test_error.rb +0 -93
- data/test/test_loggable.rb +0 -32
- data/test/test_logger.rb +0 -94
- data/test/test_node.rb +0 -469
- data/test/test_output_filesystem.rb +0 -60
- data/test/test_path.rb +0 -241
- data/test/test_source_filesystem.rb +0 -76
- data/test/test_source_resource.rb +0 -28
- data/test/test_source_stacked.rb +0 -49
- data/test/test_sourcehandler_base.rb +0 -136
- data/test/test_sourcehandler_copy.rb +0 -47
- data/test/test_sourcehandler_directory.rb +0 -38
- data/test/test_sourcehandler_feed.rb +0 -88
- data/test/test_sourcehandler_fragment.rb +0 -70
- data/test/test_sourcehandler_main.rb +0 -39
- data/test/test_sourcehandler_memory.rb +0 -44
- data/test/test_sourcehandler_metainfo.rb +0 -127
- data/test/test_sourcehandler_page.rb +0 -73
- data/test/test_sourcehandler_sitemap.rb +0 -68
- data/test/test_sourcehandler_template.rb +0 -68
- data/test/test_sourcehandler_virtual.rb +0 -106
- data/test/test_tag_base.rb +0 -62
- data/test/test_tag_breadcrumbtrail.rb +0 -91
- data/test/test_tag_coderay.rb +0 -45
- data/test/test_tag_date.rb +0 -18
- data/test/test_tag_executecommand.rb +0 -41
- data/test/test_tag_includefile.rb +0 -50
- data/test/test_tag_langbar.rb +0 -71
- data/test/test_tag_link.rb +0 -70
- data/test/test_tag_menu.rb +0 -207
- data/test/test_tag_metainfo.rb +0 -26
- data/test/test_tag_relocatable.rb +0 -60
- data/test/test_tag_sitemap.rb +0 -47
- data/test/test_tag_tikz.rb +0 -69
- data/test/test_tree.rb +0 -70
- data/test/test_website.rb +0 -130
- data/test/test_websiteaccess.rb +0 -25
- 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
|
-
#
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
@
|
|
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
|
-
#
|
|
62
|
-
def
|
|
63
|
-
|
|
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
|
|
15
|
-
# available
|
|
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
|
-
#
|
|
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
|
|
70
|
-
#
|
|
71
|
-
#
|
|
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
|
|
78
|
-
def initialize(parent,
|
|
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
|
-
|
|
83
|
-
|
|
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
|
-
@
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
|
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
|
-
#
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
#
|
|
157
|
-
|
|
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
|
-
#
|
|
173
|
-
def
|
|
174
|
-
|
|
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
|
-
#
|
|
126
|
+
# Check if the this node is an ancestor of +node+.
|
|
182
127
|
#
|
|
183
|
-
#
|
|
184
|
-
#
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
#
|
|
262
|
-
#
|
|
263
|
-
#
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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
|
|
284
|
-
#
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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(
|
|
177
|
+
(route == '' ? File.basename(@dest_path) : route)
|
|
301
178
|
end
|
|
302
179
|
|
|
303
|
-
# Return the
|
|
304
|
-
#
|
|
305
|
-
#
|
|
306
|
-
#
|
|
307
|
-
|
|
308
|
-
|
|
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
|
-
|
|
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
|
|
333
|
-
#
|
|
334
|
-
#
|
|
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
|
|
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
|
|
346
|
-
#
|
|
347
|
-
|
|
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.
|
|
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
|
-
|
|
355
|
-
attr['
|
|
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
|
-
|
|
217
|
+
"<a#{attrs}>#{link_text}</a>"
|
|
358
218
|
end
|
|
359
219
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
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
|
-
#
|
|
395
|
-
|
|
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[:
|
|
426
|
-
|
|
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
|
-
|
|
433
|
-
|
|
434
|
-
|
|
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
|
-
|
|
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
|