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,336 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'webgen/path'
|
|
4
|
+
|
|
5
|
+
module Webgen
|
|
6
|
+
|
|
7
|
+
# Used for finding nodes that match certain criterias.
|
|
8
|
+
#
|
|
9
|
+
# == About
|
|
10
|
+
#
|
|
11
|
+
# This extension class is used for finding nodes that match certain criterias (all nodes are used
|
|
12
|
+
# if no filter options are specified) when calling the #find method. There are some built-in
|
|
13
|
+
# filters but one can also provide custom filters via #add_filter_module.
|
|
14
|
+
#
|
|
15
|
+
# The found nodes are either returned in a flat list or hierarchical in nested lists (if a node
|
|
16
|
+
# has no child nodes, only the node itself is used; otherwise a two element array containing the
|
|
17
|
+
# node and child nodes is used). Sorting, limiting the number of returned nodes and using an
|
|
18
|
+
# offset are also possible.
|
|
19
|
+
#
|
|
20
|
+
# *Note* that results are cached in the volatile cache of the Cache instance!
|
|
21
|
+
#
|
|
22
|
+
# == Finder options
|
|
23
|
+
#
|
|
24
|
+
# Following is the list of all finder options. Note that there may also be other 3rd party node
|
|
25
|
+
# filters available if you are using extension bundles!
|
|
26
|
+
#
|
|
27
|
+
# === Non-filter options
|
|
28
|
+
#
|
|
29
|
+
# These options are not used for filtering out nodes but provide additional functionality.
|
|
30
|
+
#
|
|
31
|
+
# [:limit]
|
|
32
|
+
# Value: an integer. Specifies the maximum number of nodes that should be returned. Implies
|
|
33
|
+
# 'flatten = true'.
|
|
34
|
+
#
|
|
35
|
+
# Note that fewer nodes may be returned if fewer nodes match the filter criterias.
|
|
36
|
+
#
|
|
37
|
+
# [:offset]
|
|
38
|
+
# Value: an integer. Specifies how many nodes from the front of the list should *not* be
|
|
39
|
+
# returned. Implies 'flatten = true'.
|
|
40
|
+
#
|
|
41
|
+
# [:flatten]
|
|
42
|
+
# Value: anything except +nil+ or +false+. A flat list of nodes is returned if this option is
|
|
43
|
+
# set, otherwise the nodes are returned in their correct hierarchical order using nested lists.
|
|
44
|
+
#
|
|
45
|
+
# Note that any missing nodes in the hierarchy are automatically added so that traversing the
|
|
46
|
+
# hierarchy is always possible. For example, if we have the tree '/a/b/c' and only nodes +a+ and
|
|
47
|
+
# +c+ are found, node +b+ is automatically added.
|
|
48
|
+
#
|
|
49
|
+
# [:sort]
|
|
50
|
+
# Value: +nil+/+false+, +true+ or a meta information key. If +nil+ or +false+ is specified, no
|
|
51
|
+
# sorting is performed. If +true+ is specified, the meta information +sort_info+ (or if absent,
|
|
52
|
+
# the meta information +title+) is used for sorting. If the compared values are both integers, a
|
|
53
|
+
# numeric comparison is done, else a string comparison. If a meta information key is specified,
|
|
54
|
+
# the value of this meta information is used for comparison of nodes (again, if both compared
|
|
55
|
+
# values are integers, a numeric comparison is done, else a string comparison).
|
|
56
|
+
#
|
|
57
|
+
# === Filter options
|
|
58
|
+
#
|
|
59
|
+
# These options are used for filtering the nodes. All nodes are used by default if no filter
|
|
60
|
+
# options are specified.
|
|
61
|
+
#
|
|
62
|
+
# [:alcn]
|
|
63
|
+
# Value: an alcn pattern or an array of alcn patterns. Nodes that match any of the patterns are
|
|
64
|
+
# used.
|
|
65
|
+
#
|
|
66
|
+
# [:lang]
|
|
67
|
+
# Value: a language code/+nil+/the special value :+node+ or an array of these values. Nodes that
|
|
68
|
+
# have one of the specified language codes, are language independent (in case of the value
|
|
69
|
+
# +nil+) or have the same language as the reference node (in case of the value :+node+) are
|
|
70
|
+
# used.
|
|
71
|
+
#
|
|
72
|
+
# [:mi]
|
|
73
|
+
# Value: a hash with meta information key to value mappings. Only nodes that have the same
|
|
74
|
+
# values for all meta information keys are used.
|
|
75
|
+
#
|
|
76
|
+
# [:or]
|
|
77
|
+
# Value: a finder option set or an array of finder options sets (specifying option set names is
|
|
78
|
+
# also possible). Nodes that appear in any specified option set are additionally used.
|
|
79
|
+
#
|
|
80
|
+
# [:and]
|
|
81
|
+
# Value: a finder option set or an array of finder options sets (specifying option set names is
|
|
82
|
+
# also possible). Only nodes that appear in all specified option sets are used.
|
|
83
|
+
#
|
|
84
|
+
# [:not]
|
|
85
|
+
# Value: a finder option set or an array of finder options sets (specifying option set names is
|
|
86
|
+
# also possible). Only nodes that do not appear in any specified option set are used.
|
|
87
|
+
#
|
|
88
|
+
# [:levels]
|
|
89
|
+
# Value: one integer (is used as start and end level) or an array with two integers (the start
|
|
90
|
+
# and end levels). All nodes whose hierarchy levels are greater than or equal to the start level
|
|
91
|
+
# and lower than or equal to the end level are used.
|
|
92
|
+
#
|
|
93
|
+
# [:ancestors]
|
|
94
|
+
# Value: +true+ or +false+/+nil+. If this filter option is set to +true+, only nodes that are
|
|
95
|
+
# ancestors of the reference node are used. The reference node itself is used as well.
|
|
96
|
+
#
|
|
97
|
+
# [:descendants]
|
|
98
|
+
# Value: +true+ or +false+/+nil+. If this filter option is set to +true+, only nodes that are
|
|
99
|
+
# descendants of the reference node are used. The reference node itself is used as well.
|
|
100
|
+
#
|
|
101
|
+
# [:siblings]
|
|
102
|
+
# Value: +true+ or +false+/+nil+. If this filter option is set to +true+, only nodes that are
|
|
103
|
+
# siblings of the reference are node used. The reference node itself is used as well.
|
|
104
|
+
#
|
|
105
|
+
# == Implementing a filter module
|
|
106
|
+
#
|
|
107
|
+
# Implementing a filter module is very easy. Just create a module that contains your filter
|
|
108
|
+
# methods and tell the NodeFinder object about it using the #add_filter_module method. A filter
|
|
109
|
+
# method needs to take three arguments: an array of nodes, the reference node and the filter
|
|
110
|
+
# value.
|
|
111
|
+
#
|
|
112
|
+
# Here is a sample filter module which provides the ability to filter nodes based on the meta
|
|
113
|
+
# information key +category+. The +category+ key contains an array with one or more categories.
|
|
114
|
+
# The value for this category filter is one or more strings and the filter returns those nodes
|
|
115
|
+
# that contain at least one specified category.
|
|
116
|
+
#
|
|
117
|
+
# module CategoryFilter
|
|
118
|
+
#
|
|
119
|
+
# def filter_on_category(nodes, ref_node, categories)
|
|
120
|
+
# categories = [categories].flatten # needed in case categories is a string
|
|
121
|
+
# nodes.select {|n| categories.any? {|c| n['category'].include?(c)}}
|
|
122
|
+
# end
|
|
123
|
+
#
|
|
124
|
+
# end
|
|
125
|
+
#
|
|
126
|
+
# website.ext.node_finder.add_filter_module(CategoryFilter, category: 'filter_on_category')
|
|
127
|
+
#
|
|
128
|
+
class NodeFinder
|
|
129
|
+
|
|
130
|
+
# Create a new NodeFinder object for the given website.
|
|
131
|
+
def initialize(website)
|
|
132
|
+
@website = website
|
|
133
|
+
@mapping = {
|
|
134
|
+
:alcn => :filter_alcn, :levels => :filter_levels, :lang => :filter_lang,
|
|
135
|
+
:and => :filter_and, :or => :filter_or, :not => :filter_not,
|
|
136
|
+
:ancestors => :filter_ancestors, :descendants => :filter_descendants,
|
|
137
|
+
:siblings => :filter_siblings,
|
|
138
|
+
:mi => :filter_meta_info
|
|
139
|
+
}
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Add a module with filter methods.
|
|
143
|
+
#
|
|
144
|
+
# The parameter +mapping+ needs to be a hash associating unique names with the methods of the
|
|
145
|
+
# given module that can be used as finder methods.
|
|
146
|
+
#
|
|
147
|
+
# === Examples:
|
|
148
|
+
#
|
|
149
|
+
# node_finder.add_filter_module(MyModule, blog: 'filter_on_blog')
|
|
150
|
+
#
|
|
151
|
+
def add_filter_module(mod, mapping)
|
|
152
|
+
public_methods = mod.public_instance_methods.map {|c| c.to_s}
|
|
153
|
+
mapping.each do |name, method|
|
|
154
|
+
if !public_methods.include?(method.to_s)
|
|
155
|
+
raise ArgumentError, "Finder method '#{method}' not found in module #{mod}"
|
|
156
|
+
end
|
|
157
|
+
@mapping[name.intern] = method
|
|
158
|
+
end
|
|
159
|
+
extend(mod)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Return all nodes that match certain criterias.
|
|
163
|
+
#
|
|
164
|
+
# The parameter +opts_or_name+ can either be a hash with finder options or the name of a finder
|
|
165
|
+
# option set defined using the configuration option 'node_finder.options_sets'. The node
|
|
166
|
+
# +ref_node+ is used as reference node.
|
|
167
|
+
def find(opts_or_name, ref_node)
|
|
168
|
+
if result = cached_result(opts_or_name, ref_node)
|
|
169
|
+
return result
|
|
170
|
+
end
|
|
171
|
+
opts = prepare_options_hash(opts_or_name)
|
|
172
|
+
|
|
173
|
+
limit, offset, flatten, sort = remove_non_filter_options(opts)
|
|
174
|
+
flatten = true if limit || offset
|
|
175
|
+
|
|
176
|
+
nodes = filter_nodes(opts, ref_node)
|
|
177
|
+
|
|
178
|
+
if flatten
|
|
179
|
+
sort_nodes(nodes, sort)
|
|
180
|
+
nodes = nodes[(offset.to_s.to_i)..(limit ? offset.to_s.to_i + limit.to_s.to_i - 1 : -1)] if limit || offset
|
|
181
|
+
else
|
|
182
|
+
result = {}
|
|
183
|
+
min_level = 1_000_000
|
|
184
|
+
nodes.each {|n| min_level = n.level if n.level < min_level}
|
|
185
|
+
|
|
186
|
+
nodes.each do |n|
|
|
187
|
+
hierarchy_nodes = []
|
|
188
|
+
(hierarchy_nodes.unshift(n); n = n.parent) while n.level >= min_level
|
|
189
|
+
hierarchy_nodes.inject(result) {|memo, hn| memo[hn] ||= {}}
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
reducer = lambda do |h|
|
|
193
|
+
h.map {|k,v| v.empty? ? k : [k, reducer.call(v)]}
|
|
194
|
+
end
|
|
195
|
+
nodes = reducer.call(result)
|
|
196
|
+
sort_nodes(nodes, sort, false)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
cache_result(opts_or_name, ref_node, nodes)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
#######
|
|
203
|
+
private
|
|
204
|
+
#######
|
|
205
|
+
|
|
206
|
+
def cached_result(opts, ref_node)
|
|
207
|
+
(@website.cache.volatile[:node_finder] ||= {})[[opts, ref_node.alcn]]
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def cache_result(opts, ref_node, result)
|
|
211
|
+
(@website.cache.volatile[:node_finder] ||= {})[[opts, ref_node.alcn]] = result
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def prepare_options_hash(opts_or_name)
|
|
215
|
+
if Hash === opts_or_name
|
|
216
|
+
opts_or_name.symbolize_keys
|
|
217
|
+
elsif @website.config['node_finder.option_sets'].has_key?(opts_or_name)
|
|
218
|
+
@website.config['node_finder.option_sets'][opts_or_name].symbolize_keys
|
|
219
|
+
else
|
|
220
|
+
raise ArgumentError, "Invalid argument supplied, expected Hash or name of search definition, not #{opts_or_name}"
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def remove_non_filter_options(opts)
|
|
225
|
+
[opts.delete(:limit), opts.delete(:offset), opts.delete(:flatten), opts.delete(:sort)]
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def filter_nodes(opts, ref_node)
|
|
229
|
+
nodes = @website.tree.node_access[:alcn].values
|
|
230
|
+
nodes.delete(@website.tree.dummy_root)
|
|
231
|
+
|
|
232
|
+
opts.each do |filter, value|
|
|
233
|
+
if @mapping.has_key?(filter)
|
|
234
|
+
nodes = send(@mapping[filter], nodes, ref_node, value)
|
|
235
|
+
else
|
|
236
|
+
@website.logger.warn { "Ignoring unknown node finder filter '#{filter}'" }
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
nodes
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def sort_nodes(nodes, sort, flat_mode = true)
|
|
244
|
+
return unless sort
|
|
245
|
+
if sort == true
|
|
246
|
+
nodes.sort! do |(a,_),(b,_)|
|
|
247
|
+
a = (a['sort_info'] && a['sort_info'].to_s) || a['title'].to_s || ''
|
|
248
|
+
b = (b['sort_info'] && b['sort_info'].to_s) || b['title'].to_s || ''
|
|
249
|
+
(a = a.to_i; b = b.to_i) if a !~ /\D/ && b !~ /\D/
|
|
250
|
+
a <=> b
|
|
251
|
+
end
|
|
252
|
+
else
|
|
253
|
+
nodes.sort! do |(a,_),(b,_)|
|
|
254
|
+
a, b = a[sort].to_s, b[sort].to_s
|
|
255
|
+
a, b = a.to_i, b.to_i if a !~ /\D/ && b !~ /\D/
|
|
256
|
+
a <=> b
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
nodes.each {|n, children| sort_nodes(children, sort, flat_mode) if children } unless flat_mode
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# :section: Filter methods
|
|
263
|
+
|
|
264
|
+
def filter_and(nodes, ref_node, opts)
|
|
265
|
+
[opts].flatten.each do |cur_opts|
|
|
266
|
+
cur_opts = prepare_options_hash(cur_opts)
|
|
267
|
+
remove_non_filter_options(cur_opts)
|
|
268
|
+
nodes &= filter_nodes(cur_opts, ref_node)
|
|
269
|
+
end
|
|
270
|
+
nodes
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def filter_or(nodes, ref_node, opts)
|
|
274
|
+
[opts].flatten.each do |cur_opts|
|
|
275
|
+
cur_opts = prepare_options_hash(cur_opts)
|
|
276
|
+
remove_non_filter_options(cur_opts)
|
|
277
|
+
nodes |= filter_nodes(cur_opts, ref_node)
|
|
278
|
+
end
|
|
279
|
+
nodes
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def filter_not(nodes, ref_node, opts)
|
|
283
|
+
[opts].flatten.each do |cur_opts|
|
|
284
|
+
cur_opts = prepare_options_hash(cur_opts)
|
|
285
|
+
remove_non_filter_options(cur_opts)
|
|
286
|
+
nodes -= filter_nodes(cur_opts, ref_node)
|
|
287
|
+
end
|
|
288
|
+
nodes
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def filter_meta_info(nodes, ref_node, mi)
|
|
292
|
+
nodes.keep_if {|n| mi.all? {|key, val| n[key] == val}}
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def filter_alcn(nodes, ref_node, alcn)
|
|
296
|
+
alcn = [alcn].flatten.map {|a| Webgen::Path.append(ref_node.alcn, a.to_s)}
|
|
297
|
+
nodes.keep_if {|n| alcn.any? {|a| n =~ a}}
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def filter_levels(nodes, ref_node, range)
|
|
301
|
+
range = [range].flatten.map {|i| i.to_i}
|
|
302
|
+
nodes.keep_if {|n| n.level >= range.first && n.level <= range.last}
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def filter_lang(nodes, ref_node, langs)
|
|
306
|
+
langs = [langs].flatten.map {|l| l == :node ? ref_node.lang : l}.uniq
|
|
307
|
+
nodes.keep_if {|n| langs.any? {|l| n.lang == l}}
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def filter_ancestors(nodes, ref_node, enabled)
|
|
311
|
+
return nodes unless enabled
|
|
312
|
+
nodes = []
|
|
313
|
+
node = ref_node
|
|
314
|
+
until node == node.tree.dummy_root
|
|
315
|
+
nodes.unshift(node)
|
|
316
|
+
node = node.parent
|
|
317
|
+
end
|
|
318
|
+
nodes
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def filter_descendants(nodes, ref_node, enabled)
|
|
322
|
+
return nodes unless enabled
|
|
323
|
+
nodes.keep_if do |n|
|
|
324
|
+
n = n.parent while n != n.tree.dummy_root && n != ref_node
|
|
325
|
+
n == ref_node
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def filter_siblings(nodes, ref_node, enabled)
|
|
330
|
+
return nodes unless enabled
|
|
331
|
+
nodes.keep_if { |n| n.parent == ref_node.parent}
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
end
|
data/lib/webgen/page.rb
CHANGED
|
@@ -1,95 +1,49 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
2
|
|
|
3
3
|
require 'yaml'
|
|
4
|
+
require 'webgen/error'
|
|
4
5
|
|
|
5
6
|
module Webgen
|
|
6
7
|
|
|
7
|
-
# A Page object wraps a meta information hash and
|
|
8
|
-
#
|
|
8
|
+
# A Page object wraps a meta information hash and a hash of {block name => block content}
|
|
9
|
+
# associations.
|
|
10
|
+
#
|
|
11
|
+
# It is normally generated from a file or string in Webgen Page Format using the provided class
|
|
12
|
+
# methods.
|
|
9
13
|
class Page
|
|
10
14
|
|
|
11
|
-
# A single block within a Page object. The content of the block can be rendered using the #render method.
|
|
12
|
-
class Block
|
|
13
|
-
|
|
14
|
-
# The name of the block.
|
|
15
|
-
attr_reader :name
|
|
16
|
-
|
|
17
|
-
# The content of the block.
|
|
18
|
-
attr_reader :content
|
|
19
|
-
|
|
20
|
-
# The options set specifically for this block.
|
|
21
|
-
attr_reader :options
|
|
22
|
-
|
|
23
|
-
# Create a new block with the name +name+ and the given +content+ and +options+.
|
|
24
|
-
def initialize(name, content, options)
|
|
25
|
-
@name, @content, @options = name, content, options
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# Render the block using the provided context object.
|
|
29
|
-
#
|
|
30
|
-
# The context object needs to respond to <tt>#[]</tt> and <tt>#[]=</tt> (e.g. a Hash is a valid
|
|
31
|
-
# context object) and the key <tt>:processors</tt> needs to contain a Hash which maps processor
|
|
32
|
-
# names to processor objects that respond to <tt>#call</tt>.
|
|
33
|
-
#
|
|
34
|
-
# Uses the content processors specified in the +pipeline+ key of the +options+ attribute to do
|
|
35
|
-
# the actual rendering.
|
|
36
|
-
#
|
|
37
|
-
# Returns the given context with the rendered content.
|
|
38
|
-
def render(context)
|
|
39
|
-
context[:content] = @content.dup
|
|
40
|
-
context[:block] = self
|
|
41
|
-
@options['pipeline'].to_s.split(/,/).each do |processor|
|
|
42
|
-
raise "No such content processor available: #{processor}" unless context[:processors].has_key?(processor)
|
|
43
|
-
context[:processors][processor].call(context)
|
|
44
|
-
end
|
|
45
|
-
context
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
|
|
51
15
|
# Raised during parsing of data in Webgen Page Format if the data is invalid.
|
|
52
|
-
class FormatError <
|
|
16
|
+
class FormatError < Error; end
|
|
53
17
|
|
|
54
18
|
|
|
55
19
|
# :stopdoc:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
20
|
+
RE_NEWLINE = /\r?\n/
|
|
21
|
+
RE_META_INFO_START = /\A---\s*#{RE_NEWLINE}/
|
|
22
|
+
RE_META_INFO = /#{RE_META_INFO_START}.*?#{RE_NEWLINE}(?=---.*?#{RE_NEWLINE}|\Z)/m
|
|
23
|
+
RE_BLOCKS_START_SIMPLE = /^--- (\w+)(?:\s*| -+\s*)$|^$/
|
|
24
|
+
RE_BLOCKS_START_COMPLEX = /^--- *?(?: *((?:\w+:[^\s]* *)*))?-*\s*$|^$/
|
|
25
|
+
RE_BLOCKS_START = /^---(?: .*?|)(?=#{RE_NEWLINE})/
|
|
26
|
+
RE_BLOCKS = /(?:(#{RE_BLOCKS_START})|\A)#{RE_NEWLINE}?(.*?)(?:(?=#{RE_BLOCKS_START})|\z)/m
|
|
27
|
+
RE_PAGE = /(#{RE_META_INFO})?(.*)/m
|
|
61
28
|
# :startdoc:
|
|
62
29
|
|
|
63
30
|
class << self
|
|
64
31
|
|
|
65
|
-
# Parse the given string +data+ in Webgen Page Format
|
|
66
|
-
#
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
32
|
+
# Parse the given string +data+ in Webgen Page Format.
|
|
33
|
+
#
|
|
34
|
+
# This method returns a Page object containing the hash with the meta information and the
|
|
35
|
+
# parsed blocks.
|
|
36
|
+
def from_data(data)
|
|
37
|
+
md = RE_PAGE.match(data)
|
|
38
|
+
meta_info = parse_meta_info(md[1], data =~ RE_META_INFO_START)
|
|
70
39
|
blocks = parse_blocks(md[2] || '', meta_info)
|
|
71
40
|
new(meta_info, blocks)
|
|
72
41
|
end
|
|
73
42
|
|
|
74
|
-
# Parse the given string +data+ in Webgen Page Format and return the found meta information.
|
|
75
|
-
def meta_info_from_data(data)
|
|
76
|
-
md = /(#{RE_META_INFO})?/m.match(normalize_eol(data))
|
|
77
|
-
parse_meta_info(md[1], data)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
#######
|
|
81
|
-
private
|
|
82
|
-
#######
|
|
83
|
-
|
|
84
|
-
# Normalize the end-of-line encodings to Unix style.
|
|
85
|
-
def normalize_eol(data)
|
|
86
|
-
data.gsub(/\r\n?/, "\n")
|
|
87
|
-
end
|
|
88
|
-
|
|
89
43
|
# Parse the meta info string in +mi_data+ and return the hash with the meta information. The
|
|
90
44
|
# original +data+ is used for checking the validness of the meta information block.
|
|
91
|
-
def parse_meta_info(mi_data,
|
|
92
|
-
if mi_data.nil? &&
|
|
45
|
+
def parse_meta_info(mi_data, has_mi_start)
|
|
46
|
+
if mi_data.nil? && has_mi_start
|
|
93
47
|
raise FormatError, 'Found start line for meta information block but no valid meta information block'
|
|
94
48
|
elsif mi_data.nil?
|
|
95
49
|
{}
|
|
@@ -99,39 +53,48 @@ module Webgen
|
|
|
99
53
|
unless meta_info.kind_of?(Hash)
|
|
100
54
|
raise FormatError, "Invalid structure of meta information block: expected YAML hash but found #{meta_info.class}"
|
|
101
55
|
end
|
|
102
|
-
rescue ArgumentError => e
|
|
56
|
+
rescue ArgumentError, SyntaxError => e
|
|
103
57
|
raise FormatError, "Invalid YAML syntax in meta information block: #{e.message}"
|
|
104
58
|
end
|
|
105
59
|
meta_info
|
|
106
60
|
end
|
|
107
61
|
end
|
|
62
|
+
private :parse_meta_info
|
|
108
63
|
|
|
109
|
-
# Parse all blocks in +data+ and return them.
|
|
110
|
-
#
|
|
64
|
+
# Parse all blocks in +data+ and return them.
|
|
65
|
+
#
|
|
66
|
+
# The key 'blocks' of the meta information hash is updated with information found on block
|
|
67
|
+
# starting lines.
|
|
111
68
|
def parse_blocks(data, meta_info)
|
|
112
69
|
scanned = data.scan(RE_BLOCKS)
|
|
113
70
|
raise(FormatError, 'No content blocks specified') if scanned.length == 0
|
|
114
71
|
|
|
115
72
|
blocks = {}
|
|
116
73
|
scanned.each_with_index do |block_data, index|
|
|
74
|
+
index += 1
|
|
117
75
|
options, content = *block_data
|
|
118
|
-
md =
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
76
|
+
if md = RE_BLOCKS_START_SIMPLE.match(options.to_s)
|
|
77
|
+
options = {'name' => md[1]}
|
|
78
|
+
else
|
|
79
|
+
md = RE_BLOCKS_START_COMPLEX.match(options.to_s)
|
|
80
|
+
raise(FormatError, "Found invalid blocks starting line for block #{index}: #{options}") if content =~ /\A---/ || md.nil?
|
|
81
|
+
options = Hash[*md[1].to_s.scan(/(\w+):([^\s]*)/).map {|k,v| [k, (v == '' ? nil : YAML::load(v))]}.flatten]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
name = options.delete('name') || (index == 1 ? 'content' : 'block' + (index).to_s)
|
|
85
|
+
raise(FormatError, "Previously used name '#{name}' also used for block #{index}") if blocks.has_key?(name)
|
|
127
86
|
content ||= ''
|
|
128
87
|
content.gsub!(/^(\\+)(---.*?)$/) {|m| "\\" * ($1.length / 2) + $2}
|
|
129
|
-
content.chomp!
|
|
130
|
-
|
|
88
|
+
content.chomp! unless index == scanned.length
|
|
89
|
+
|
|
90
|
+
blocks[name] = content
|
|
91
|
+
((meta_info['blocks'] ||= {})[name] ||= {}).merge!(options) unless options.empty?
|
|
131
92
|
end
|
|
132
|
-
meta_info.
|
|
93
|
+
meta_info['blocks'].delete_if {|k,v| v.empty?} if meta_info.has_key?('blocks')
|
|
94
|
+
meta_info.delete('blocks') if meta_info.has_key?('blocks') && meta_info['blocks'].empty?
|
|
133
95
|
blocks
|
|
134
96
|
end
|
|
97
|
+
private :parse_blocks
|
|
135
98
|
|
|
136
99
|
end
|
|
137
100
|
|